Skip to content

Commit 2150743

Browse files
feat: Modern way of configuring json layout via JsonTemplateLayout
1 parent 1bdafd3 commit 2150743

File tree

8 files changed

+190
-3
lines changed

8 files changed

+190
-3
lines changed

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@
167167
<artifactId>log4j-api</artifactId>
168168
<version>${log4j.version}</version>
169169
</dependency>
170+
<dependency>
171+
<groupId>org.apache.logging.log4j</groupId>
172+
<artifactId>log4j-layout-template-json</artifactId>
173+
<version>${log4j.version}</version>
174+
</dependency>
170175
<dependency>
171176
<groupId>org.apache.logging.log4j</groupId>
172177
<artifactId>log4j-jcl</artifactId>

powertools-logging/pom.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@
5353
<groupId>com.fasterxml.jackson.core</groupId>
5454
<artifactId>jackson-databind</artifactId>
5555
</dependency>
56-
56+
<dependency>
57+
<groupId>org.apache.logging.log4j</groupId>
58+
<artifactId>log4j-layout-template-json</artifactId>
59+
</dependency>
5760
<dependency>
5861
<groupId>org.apache.logging.log4j</groupId>
5962
<artifactId>log4j-core</artifactId>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package software.amazon.lambda.powertools.logging;
2+
3+
import org.apache.logging.log4j.core.LogEvent;
4+
import org.apache.logging.log4j.layout.template.json.resolver.EventResolver;
5+
import org.apache.logging.log4j.layout.template.json.util.JsonWriter;
6+
import org.apache.logging.log4j.util.ReadOnlyStringMap;
7+
8+
public final class PowertoolsResolver implements EventResolver {
9+
10+
private final EventResolver internalResolver;
11+
12+
PowertoolsResolver() {
13+
internalResolver = new EventResolver() {
14+
@Override
15+
public boolean isResolvable(LogEvent value) {
16+
ReadOnlyStringMap contextData = value.getContextData();
17+
return null != contextData && !contextData.isEmpty();
18+
}
19+
20+
@Override
21+
public void resolve(LogEvent logEvent, JsonWriter jsonWriter) {
22+
StringBuilder stringBuilder = jsonWriter.getStringBuilder();
23+
// remove dummy field to kick inn powertools resolver
24+
stringBuilder.setLength(stringBuilder.length() - 4);
25+
26+
// Inject all the context information.
27+
ReadOnlyStringMap contextData = logEvent.getContextData();
28+
contextData.forEach((key, value) -> {
29+
jsonWriter.writeSeparator();
30+
jsonWriter.writeString(key);
31+
stringBuilder.append(':');
32+
jsonWriter.writeValue(value);
33+
});
34+
}
35+
};
36+
}
37+
38+
static String getName() {
39+
return "powertools";
40+
}
41+
42+
@Override
43+
public void resolve(LogEvent value, JsonWriter jsonWriter) {
44+
internalResolver.resolve(value, jsonWriter);
45+
}
46+
47+
@Override
48+
public boolean isResolvable(LogEvent value) {
49+
return internalResolver.isResolvable(value);
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package software.amazon.lambda.powertools.logging;
2+
3+
import org.apache.logging.log4j.core.LogEvent;
4+
import org.apache.logging.log4j.core.config.plugins.Plugin;
5+
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
6+
import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext;
7+
import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory;
8+
import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver;
9+
import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig;
10+
import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory;
11+
12+
@Plugin(name = "PowertoolsResolverFactory", category = TemplateResolverFactory.CATEGORY)
13+
public final class PowertoolsResolverFactory implements EventResolverFactory {
14+
15+
private static final PowertoolsResolverFactory INSTANCE = new PowertoolsResolverFactory();
16+
17+
private PowertoolsResolverFactory() {}
18+
19+
@PluginFactory
20+
public static PowertoolsResolverFactory getInstance() {
21+
return INSTANCE;
22+
}
23+
24+
@Override
25+
public String getName() {
26+
return PowertoolsResolver.getName();
27+
}
28+
29+
@Override
30+
public TemplateResolver<LogEvent> create(EventResolverContext context,
31+
TemplateResolverConfig config) {
32+
return new PowertoolsResolver();
33+
}
34+
}

powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonLayout.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
import static java.time.Instant.ofEpochMilli;
4444
import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME;
4545

46+
/***
47+
* Note: The LambdaJsonLayout should be considered to be deprecated. Please use JsonTemplateLayout instead.
48+
*/
4649
@Plugin(name = "LambdaJsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
4750
public final class LambdaJsonLayout extends AbstractJacksonLayoutCopy {
4851
private static final String DEFAULT_FOOTER = "]";
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"timestamp": {
3+
"$resolver": "timestamp"
4+
},
5+
"instant": {
6+
"epochSecond": {
7+
"$resolver": "timestamp",
8+
"epoch": {
9+
"unit": "secs",
10+
"rounded": true
11+
}
12+
},
13+
"nanoOfSecond": {
14+
"$resolver": "timestamp",
15+
"epoch": {
16+
"unit": "secs.nanos"
17+
}
18+
}
19+
},
20+
"thread": {
21+
"$resolver": "thread",
22+
"field": "name"
23+
},
24+
"level": {
25+
"$resolver": "level",
26+
"field": "name"
27+
},
28+
"loggerName": {
29+
"$resolver": "logger",
30+
"field": "name"
31+
},
32+
"message": {
33+
"$resolver": "message",
34+
"stringified": true
35+
},
36+
"thrown": {
37+
"message": {
38+
"$resolver": "exception",
39+
"field": "message"
40+
},
41+
"name": {
42+
"$resolver": "exception",
43+
"field": "className"
44+
},
45+
"extendedStackTrace": {
46+
"$resolver": "exception",
47+
"field": "stackTrace"
48+
}
49+
},
50+
"contextStack": {
51+
"$resolver": "ndc"
52+
},
53+
"endOfBatch": {
54+
"$resolver": "endOfBatch"
55+
},
56+
"loggerFqcn": {
57+
"$resolver": "logger",
58+
"field": "fqcn"
59+
},
60+
"threadId": {
61+
"$resolver": "thread",
62+
"field": "id"
63+
},
64+
"threadPriority": {
65+
"$resolver": "thread",
66+
"field": "priority"
67+
},
68+
"source": {
69+
"class": {
70+
"$resolver": "source",
71+
"field": "className"
72+
},
73+
"method": {
74+
"$resolver": "source",
75+
"field": "methodName"
76+
},
77+
"file": {
78+
"$resolver": "source",
79+
"field": "fileName"
80+
},
81+
"line": {
82+
"$resolver": "source",
83+
"field": "lineNumber"
84+
}
85+
},
86+
"": {
87+
"$resolver": "powertools"
88+
}
89+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
log4j.layout.jsonTemplate.timestampFormatPattern=yyyy-MM-dd'T'HH:mm:ss.SSSZz
2+
#log4j.layout.jsonTemplate.timeZone=

powertools-logging/src/test/resources/log4j2.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<Configuration packages="com.amazonaws.services.lambda.runtime.log4j2">
2+
<Configuration>
33
<Appenders>
44
<File name="JsonAppender" fileName="target/logfile.json">
5-
<LambdaJsonLayout compact="true" eventEol="true"/>
5+
<JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" />
66
</File>
77
</Appenders>
88
<Loggers>

0 commit comments

Comments
 (0)