in logstash-core/src/main/java/org/logstash/StringInterpolation.java [66:137]
public static String evaluate(final Event event, final String template) throws JsonProcessingException {
int open = template.indexOf("%{");
int close = template.indexOf('}', open);
if (open == -1 || close == -1) {
return template;
}
final StringBuilder builder = STRING_BUILDER.get();
int pos = 0;
final int len = template.length();
while (open > -1 && close > -1) {
if (open > 0) {
builder.append(template, pos, open);
}
if (template.regionMatches(open + 2, "+%s", 0, close - open - 2)) {
// UNIX-style @timestamp formatter:
// - `%{+%s}` -> 1234567890
Timestamp t = event.getTimestamp();
builder.append(t == null ? "" : t.toInstant().getEpochSecond());
} else if (template.charAt(open+2) == '{' && (close < len) && template.charAt(close+1) == '}') {
// JAVA-style @timestamp formatter:
// - `%{{yyyy-MM-dd}}` -> `2021-08-11`
// - `%{{YYYY-'W'ww}}` -> `2021-W32`
// A special pattern to generate a fresh current time
// - `%{{TIME_NOW}}` -> `2025-01-16T16:57:12.488955Z`
close = close + 1; // consume extra closing squiggle
final String pattern = template.substring(open+3, close-1);
if (pattern.equals(TIME_NOW)) {
builder.append(new Timestamp());
} else {
Optional.ofNullable(event.getTimestamp())
.map(Timestamp::toInstant)
.map(instant -> DateTimeFormatter.ofPattern(pattern)
.withZone(ZoneOffset.UTC)
.format(instant))
.ifPresent(builder::append);
}
} else if (template.charAt(open + 2) == '+') {
// JODA-style @timestamp formatter:
// - `%{+YYYY.MM.dd}` -> `2021-08-11`
// - `%{+xxxx-'W'ww} -> `2021-W32`
final Timestamp t = event.getTimestamp();
if (t != null) {
final String jodaTimeFormatPattern = template.substring(open + 3, close);
final org.joda.time.format.DateTimeFormatter jodaDateTimeFormatter = DateTimeFormat.forPattern(jodaTimeFormatPattern).withZone(DateTimeZone.UTC);
final DateTime jodaTimestamp = new DateTime(t.toInstant().toEpochMilli(), DateTimeZone.UTC);
final String formattedTimestamp = jodaTimestamp.toString(jodaDateTimeFormatter);
builder.append(formattedTimestamp);
}
} else {
final String found = template.substring(open + 2, close);
final Object value = event.getField(found);
if (value != null) {
if (value instanceof List) {
builder.append(KeyNode.join((List) value, ","));
} else if (value instanceof Map) {
builder.append(ObjectMappers.JSON_MAPPER.writeValueAsString(value));
} else {
builder.append(value.toString());
}
} else {
builder.append("%{").append(found).append('}');
}
}
pos = close + 1;
open = template.indexOf("%{", pos);
close = template.indexOf('}', open);
}
if (pos < len) {
builder.append(template, pos, len);
}
return builder.toString();
}