Skip to content

Commit 0b4386f

Browse files
committed
complete tests for logback
1 parent 4488716 commit 0b4386f

File tree

14 files changed

+800
-77
lines changed

14 files changed

+800
-77
lines changed

powertools-logging/powertools-logging-logback/pom.xml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,57 @@
113113
<artifactId>jsonassert</artifactId>
114114
<scope>test</scope>
115115
</dependency>
116+
<dependency>
117+
<groupId>org.junit-pioneer</groupId>
118+
<artifactId>junit-pioneer</artifactId>
119+
<scope>test</scope>
120+
</dependency>
116121
</dependencies>
117122

118123
<build>
119124
<plugins>
125+
<plugin>
126+
<groupId>dev.aspectj</groupId>
127+
<artifactId>aspectj-maven-plugin</artifactId>
128+
<version>1.13.1</version>
129+
<configuration>
130+
<source>${maven.compiler.source}</source>
131+
<target>${maven.compiler.target}</target>
132+
<complianceLevel>${maven.compiler.target}</complianceLevel>
133+
<aspectLibraries>
134+
<aspectLibrary>
135+
<groupId>software.amazon.lambda</groupId>
136+
<artifactId>powertools-logging</artifactId>
137+
</aspectLibrary>
138+
</aspectLibraries>
139+
</configuration>
140+
<executions>
141+
<execution>
142+
<goals>
143+
<goal>compile</goal>
144+
</goals>
145+
</execution>
146+
</executions>
147+
<dependencies>
148+
<dependency>
149+
<groupId>org.aspectj</groupId>
150+
<artifactId>aspectjtools</artifactId>
151+
<version>${aspectj.version}</version>
152+
</dependency>
153+
</dependencies>
154+
</plugin>
120155
<plugin>
121156
<groupId>org.apache.maven.plugins</groupId>
122157
<artifactId>maven-checkstyle-plugin</artifactId>
123158
</plugin>
159+
<plugin>
160+
<artifactId>maven-surefire-plugin</artifactId>
161+
<configuration>
162+
<systemPropertyVariables>
163+
<slf4j.binding>ch.qos.logback.classic.spi.LogbackServiceProvider</slf4j.binding>
164+
</systemPropertyVariables>
165+
</configuration>
166+
</plugin>
124167
</plugins>
125168
</build>
126169

powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/LambdaEcsEncoder.java

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ public class LambdaEcsEncoder extends EncoderBase<ILoggingEvent> {
5151

5252
private final ThrowableProxyConverter throwableProxyConverter = new ThrowableProxyConverter();
5353
protected ThrowableHandlingConverter throwableConverter = null;
54+
private boolean includeCloudInfo = true;
55+
private boolean includeFaasInfo = true;
5456

5557
@Override
5658
public byte[] headerBytes() {
@@ -67,12 +69,6 @@ public byte[] encode(ILoggingEvent event) {
6769
LambdaEcsSerializer.serializeEcsVersion(builder, ECS_VERSION);
6870
LambdaEcsSerializer.serializeLogLevel(builder, event.getLevel());
6971
LambdaEcsSerializer.serializeFormattedMessage(builder, event.getFormattedMessage());
70-
LambdaEcsSerializer.serializeServiceName(builder, LambdaHandlerProcessor.serviceName());
71-
LambdaEcsSerializer.serializeServiceVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName()));
72-
// TODO : Environment ?
73-
LambdaEcsSerializer.serializeEventDataset(builder, LambdaHandlerProcessor.serviceName());
74-
LambdaEcsSerializer.serializeThreadName(builder, event.getThreadName());
75-
LambdaEcsSerializer.serializeLoggerName(builder, event.getLoggerName());
7672
IThrowableProxy throwableProxy = event.getThrowableProxy();
7773
if (throwableProxy != null) {
7874
if (throwableConverter != null) {
@@ -85,22 +81,33 @@ public byte[] encode(ILoggingEvent event) {
8581
throwableProxy.getMessage(), throwableProxyConverter.convert(event));
8682
}
8783
}
88-
LambdaEcsSerializer.serializeCloudProvider(builder, CLOUD_PROVIDER);
89-
LambdaEcsSerializer.serializeCloudService(builder, CLOUD_SERVICE);
84+
LambdaEcsSerializer.serializeServiceName(builder, LambdaHandlerProcessor.serviceName());
85+
LambdaEcsSerializer.serializeServiceVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName()));
86+
LambdaEcsSerializer.serializeLoggerName(builder, event.getLoggerName());
87+
LambdaEcsSerializer.serializeThreadName(builder, event.getThreadName());
9088
String arn = mdcPropertyMap.get(FUNCTION_ARN.getName());
91-
if (arn != null) {
92-
String[] arnParts = arn.split(":");
93-
LambdaEcsSerializer.serializeCloudRegion(builder, arnParts[3]);
94-
LambdaEcsSerializer.serializeCloudAccountId(builder, arnParts[4]);
89+
90+
if (includeCloudInfo) {
91+
LambdaEcsSerializer.serializeCloudProvider(builder, CLOUD_PROVIDER);
92+
LambdaEcsSerializer.serializeCloudService(builder, CLOUD_SERVICE);
93+
if (arn != null) {
94+
String[] arnParts = arn.split(":");
95+
LambdaEcsSerializer.serializeCloudRegion(builder, arnParts[3]);
96+
LambdaEcsSerializer.serializeCloudAccountId(builder, arnParts[4]);
97+
}
98+
}
99+
100+
if (includeFaasInfo) {
101+
LambdaEcsSerializer.serializeFunctionId(builder, arn);
102+
LambdaEcsSerializer.serializeFunctionName(builder, mdcPropertyMap.get(FUNCTION_NAME.getName()));
103+
LambdaEcsSerializer.serializeFunctionVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName()));
104+
LambdaEcsSerializer.serializeFunctionMemory(builder, mdcPropertyMap.get(FUNCTION_MEMORY_SIZE.getName()));
105+
LambdaEcsSerializer.serializeFunctionExecutionId(builder,
106+
mdcPropertyMap.get(FUNCTION_REQUEST_ID.getName()));
107+
LambdaEcsSerializer.serializeColdStart(builder, mdcPropertyMap.get(FUNCTION_COLD_START.getName()));
108+
LambdaEcsSerializer.serializeTraceId(builder, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName()));
95109
}
96-
LambdaEcsSerializer.serializeFunctionId(builder, arn);
97-
LambdaEcsSerializer.serializeFunctionName(builder, mdcPropertyMap.get(FUNCTION_NAME.getName()));
98-
LambdaEcsSerializer.serializeFunctionVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName()));
99-
LambdaEcsSerializer.serializeFunctionMemory(builder, mdcPropertyMap.get(FUNCTION_MEMORY_SIZE.getName()));
100-
LambdaEcsSerializer.serializeFunctionExecutionId(builder, mdcPropertyMap.get(FUNCTION_REQUEST_ID.getName()));
101-
LambdaEcsSerializer.serializeColdStart(builder, mdcPropertyMap.get(FUNCTION_COLD_START.getName()));
102110
LambdaEcsSerializer.serializeAdditionalFields(builder, event.getMDCPropertyMap());
103-
LambdaEcsSerializer.serializeTraceId(builder, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName()));
104111
LambdaEcsSerializer.serializeObjectEnd(builder);
105112
return builder.toString().getBytes(UTF_8);
106113
}
@@ -110,7 +117,73 @@ public byte[] footerBytes() {
110117
return null;
111118
}
112119

120+
/**
121+
* Specify a throwable converter to format the stacktrace according to your need (default is <b>null</b>, no throwableConverter):
122+
* <br/>
123+
* <pre>{@code
124+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaEcsEncoder">
125+
* <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
126+
* <maxDepthPerThrowable>30</maxDepthPerThrowable>
127+
* <maxLength>2048</maxLength>
128+
* <shortenedClassNameLength>20</shortenedClassNameLength>
129+
* <exclude>sun\.reflect\..*\.invoke.*</exclude>
130+
* <exclude>net\.sf\.cglib\.proxy\.MethodProxy\.invoke</exclude>
131+
* <evaluator class="myorg.MyCustomEvaluator"/>
132+
* <rootCauseFirst>true</rootCauseFirst>
133+
* <inlineHash>true</inlineHash>
134+
* </throwableConverter>
135+
* </encoder>
136+
* }</pre>
137+
* @param throwableConverter
138+
*/
113139
public void setThrowableConverter(ThrowableHandlingConverter throwableConverter) {
114140
this.throwableConverter = throwableConverter;
115141
}
142+
143+
/**
144+
* Specify if cloud information should be logged (default is <b>true</b>):
145+
* <ul>
146+
* <li>cloud.provider</li>
147+
* <li>cloud.service.name</li>
148+
* <li>cloud.region</li>
149+
* <li>cloud.account.id</li>
150+
* </ul>
151+
* <br/>
152+
* We strongly recommend to keep these information.
153+
* <br/>
154+
* <pre>{@code
155+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaEcsEncoder">
156+
* <includeCloudInfo>false</includeCloudInfo>
157+
* </encoder>
158+
* }</pre>
159+
* @param includeCloudInfo if thread information should be logged
160+
*/
161+
public void setIncludeCloudInfo(boolean includeCloudInfo) {
162+
this.includeCloudInfo = includeCloudInfo;
163+
}
164+
165+
/**
166+
* Specify if Lambda function information should be logged (default is <b>true</b>):
167+
* <ul>
168+
* <li>faas.id</li>
169+
* <li>faas.name</li>
170+
* <li>faas.version</li>
171+
* <li>faas.memory</li>
172+
* <li>faas.execution</li>
173+
* <li>faas.coldstart</li>
174+
* <li>trace.id</li>
175+
* </ul>
176+
* <br/>
177+
* We strongly recommend to keep these information.
178+
* <br/>
179+
* <pre>{@code
180+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaEcsEncoder">
181+
* <includeFaasInfo>false</includeFaasInfo>
182+
* </encoder>
183+
* }</pre>
184+
* @param includeFaasInfo if function information should be logged
185+
*/
186+
public void setIncludeFaasInfo(boolean includeFaasInfo) {
187+
this.includeFaasInfo = includeFaasInfo;
188+
}
116189
}

powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/LambdaJsonEncoder.java

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class LambdaJsonEncoder extends EncoderBase<ILoggingEvent> {
3535
protected String timestampFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZz";
3636
protected String timestampFormatTimezoneId = null;
3737
private boolean includeThreadInfo = false;
38+
private boolean includePowertoolsInfo = true;
3839

3940
@Override
4041
public byte[] headerBytes() {
@@ -68,7 +69,7 @@ public byte[] encode(ILoggingEvent event) {
6869
throwableProxy.getMessage(), throwableProxyConverter.convert(event));
6970
}
7071
}
71-
LambdaJsonSerializer.serializePowertools(builder, event.getMDCPropertyMap());
72+
LambdaJsonSerializer.serializePowertools(builder, event.getMDCPropertyMap(), includePowertoolsInfo);
7273
if (includeThreadInfo) {
7374
LambdaJsonSerializer.serializeThreadName(builder, event.getThreadName());
7475
LambdaJsonSerializer.serializeThreadId(builder, String.valueOf(Thread.currentThread().getId()));
@@ -85,19 +86,95 @@ public byte[] footerBytes() {
8586
return null;
8687
}
8788

89+
/**
90+
* Specify the format of the timestamp (default is <b>yyyy-MM-dd'T'HH:mm:ss.SSSZz</b>):
91+
* <br/>
92+
* <pre>{@code
93+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaJsonEncoder">
94+
* <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSZz</timestampFormat>
95+
* </encoder>
96+
* }</pre>
97+
* @param timestampFormat format of the timestamp (compatible with {@link java.text.SimpleDateFormat})
98+
*/
8899
public void setTimestampFormat(String timestampFormat) {
89100
this.timestampFormat = timestampFormat;
90101
}
91102

103+
/**
104+
* Specify the format of the time zone id for timestamp (default is <b>null</b>, no timezone):
105+
* <br/>
106+
* <pre>{@code
107+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaJsonEncoder">
108+
* <timestampFormatTimezoneId>Europe/Paris</timestampFormatTimezoneId>
109+
* </encoder>
110+
* }</pre>
111+
* @param timestampFormatTimezoneId Zone Id (see {@link java.util.TimeZone})
112+
*/
92113
public void setTimestampFormatTimezoneId(String timestampFormatTimezoneId) {
93114
this.timestampFormatTimezoneId = timestampFormatTimezoneId;
94115
}
95116

117+
/**
118+
* Specify a throwable converter to format the stacktrace according to your need (default is <b>null</b>, no throwableConverter):
119+
* <br/>
120+
* <pre>{@code
121+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaJsonEncoder">
122+
* <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
123+
* <maxDepthPerThrowable>30</maxDepthPerThrowable>
124+
* <maxLength>2048</maxLength>
125+
* <shortenedClassNameLength>20</shortenedClassNameLength>
126+
* <exclude>sun\.reflect\..*\.invoke.*</exclude>
127+
* <exclude>net\.sf\.cglib\.proxy\.MethodProxy\.invoke</exclude>
128+
* <evaluator class="myorg.MyCustomEvaluator"/>
129+
* <rootCauseFirst>true</rootCauseFirst>
130+
* <inlineHash>true</inlineHash>
131+
* </throwableConverter>
132+
* </encoder>
133+
* }</pre>
134+
* @param throwableConverter
135+
*/
96136
public void setThrowableConverter(ThrowableHandlingConverter throwableConverter) {
97137
this.throwableConverter = throwableConverter;
98138
}
99139

140+
/**
141+
* Specify if thread information should be logged (default is <b>false</b>)
142+
* <br/>
143+
* <pre>{@code
144+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaJsonEncoder">
145+
* <includeThreadInfo>true</includeThreadInfo>
146+
* </encoder>
147+
* }</pre>
148+
* @param includeThreadInfo if thread information should be logged
149+
*/
100150
public void setIncludeThreadInfo(boolean includeThreadInfo) {
101151
this.includeThreadInfo = includeThreadInfo;
102152
}
153+
154+
/**
155+
* Specify if Lambda function information should be logged (default is <b>true</b>):
156+
* <ul>
157+
* <li>function_name</li>
158+
* <li>function_version</li>
159+
* <li>function_arn</li>
160+
* <li>function_memory_size</li>
161+
* <li>function_request_id</li>
162+
* <li>cold_start</li>
163+
* <li>xray_trace_id</li>
164+
* <li>sampling_rate</li>
165+
* <li>service</li>
166+
* </ul>
167+
* <br/>
168+
* We strongly recommend to keep these information.
169+
* <br/>
170+
* <pre>{@code
171+
* <encoder class="software.amazon.lambda.powertools.logging.LambdaJsonEncoder">
172+
* <includePowertoolsInfo>false</includePowertoolsInfo>
173+
* </encoder>
174+
* }</pre>
175+
* @param includePowertoolsInfo if function information should be logged
176+
*/
177+
public void setIncludePowertoolsInfo(boolean includePowertoolsInfo) {
178+
this.includePowertoolsInfo = includePowertoolsInfo;
179+
}
103180
}

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ public class JsonUtils {
1919
protected static void serializeAttribute(StringBuilder builder, String attr, String value, boolean notBegin) {
2020
if (value != null) {
2121
if (notBegin) {
22-
builder.append(", ");
22+
builder.append(",");
2323
}
24-
builder.append("\"").append(attr).append("\": ");
24+
builder.append("\"").append(attr).append("\":");
2525
boolean isString = isString(value);
2626
if (isString) {
2727
builder.append("\"");
@@ -37,11 +37,11 @@ protected static void serializeAttributeAsString(StringBuilder builder, String a
3737
boolean notBegin) {
3838
if (value != null) {
3939
if (notBegin) {
40-
builder.append(", ");
40+
builder.append(",");
4141
}
4242
builder.append("\"")
4343
.append(attr)
44-
.append("\": \"")
44+
.append("\":\"")
4545
.append(value)
4646
.append("\"");
4747
}
@@ -72,7 +72,7 @@ private static boolean isString(String str) {
7272
* Taken from commons-lang3 NumberUtils to avoid include the library
7373
*/
7474
private static boolean isNumeric(final String str) {
75-
if (str == null || str.length() == 0) {
75+
if (str == null || str.isEmpty()) {
7676
return false;
7777
}
7878
if (str.charAt(str.length() - 1) == '.') {

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ public static void serializeServiceVersion(StringBuilder builder, String service
137137
serializeAttributeAsString(builder, SERVICE_VERSION_ATTR_NAME, serviceVersion);
138138
}
139139

140-
public static void serializeEventDataset(StringBuilder builder, String serviceName) {
141-
serializeAttributeAsString(builder, EVENT_DATASET_ATTR_NAME, serviceName);
142-
}
143-
144140
public static void serializeLoggerName(StringBuilder builder, String loggerName) {
145141
serializeAttributeAsString(builder, LOGGER_ATTR_NAME, loggerName);
146142
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ public static void serializeFormattedMessage(StringBuilder builder, String forma
8787
}
8888

8989
public static void serializeException(StringBuilder builder, String className, String message, String stackTrace) {
90-
builder.append("\"").append(EXCEPTION_ATTR_NAME).append("\": {");
90+
builder.append(",\"").append(EXCEPTION_ATTR_NAME).append("\":{");
9191
serializeAttribute(builder, EXCEPTION_MSG_ATTR_NAME, message, false);
9292
serializeAttribute(builder, EXCEPTION_CLASS_ATTR_NAME, className);
9393
serializeAttribute(builder, EXCEPTION_STACK_ATTR_NAME, stackTrace);
94-
builder.append("},");
94+
builder.append("}");
9595
}
9696

9797
public static void serializeException(StringBuilder builder, Throwable throwable) {
@@ -107,10 +107,13 @@ public static void serializeThreadPriority(StringBuilder builder, String threadP
107107
serializeAttribute(builder, THREAD_PRIORITY_ATTR_NAME, threadPriority);
108108
}
109109

110-
public static void serializePowertools(StringBuilder builder, Map<String, String> mdc) {
110+
public static void serializePowertools(StringBuilder builder, Map<String, String> mdc, boolean includePowertoolsInfo) {
111111
TreeMap<String, String> sortedMap = new TreeMap<>(mdc);
112-
sortedMap.forEach((k, v) ->
113-
serializeAttribute(builder, k, v));
112+
sortedMap.forEach((k, v) -> {
113+
if ((PowertoolsLoggedFields.stringValues().contains(k) && includePowertoolsInfo) || !PowertoolsLoggedFields.stringValues().contains(k)) {
114+
serializeAttribute(builder, k, v);
115+
}
116+
});
114117
}
115118

116119
}

0 commit comments

Comments
 (0)