Skip to content

Commit f543b68

Browse files
authored
fix(logging): Fix bug where correlation_id field was missing in JSON structured output (#2256)
1 parent e1dbd95 commit f543b68

File tree

7 files changed

+50
-11
lines changed

7 files changed

+50
-11
lines changed

powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package org.apache.logging.log4j.layout.template.json.resolver;
1616

1717
import static java.util.Arrays.stream;
18+
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID;
1819
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN;
1920
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START;
2021
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE;
@@ -112,7 +113,7 @@ public boolean isResolvable(LogEvent logEvent) {
112113
final String samplingRate =
113114
logEvent.getContextData().getValue(PowertoolsLoggedFields.SAMPLING_RATE.getName());
114115
try {
115-
return (null != samplingRate && Float.parseFloat(samplingRate) > 0.f);
116+
return null != samplingRate && Float.parseFloat(samplingRate) > 0.f;
116117
} catch (NumberFormatException nfe) {
117118
return false;
118119
}
@@ -142,6 +143,22 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) {
142143
}
143144
};
144145

146+
private static final EventResolver CORRELATION_ID_RESOLVER = new EventResolver() {
147+
@Override
148+
public boolean isResolvable(LogEvent logEvent) {
149+
final String correlationId =
150+
logEvent.getContextData().getValue(PowertoolsLoggedFields.CORRELATION_ID.getName());
151+
return null != correlationId;
152+
}
153+
154+
@Override
155+
public void resolve(LogEvent logEvent, JsonWriter jsonWriter) {
156+
final String correlationId =
157+
logEvent.getContextData().getValue(PowertoolsLoggedFields.CORRELATION_ID.getName());
158+
jsonWriter.writeString(correlationId);
159+
}
160+
};
161+
145162
private static final EventResolver SERVICE_RESOLVER =
146163
(final LogEvent logEvent, final JsonWriter jsonWriter) -> {
147164
final String service = logEvent.getContextData().getValue(PowertoolsLoggedFields.SERVICE.getName());
@@ -214,6 +231,7 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) {
214231
{ FUNCTION_REQUEST_ID.getName(), FUNCTION_REQ_RESOLVER },
215232
{ FUNCTION_COLD_START.getName(), COLD_START_RESOLVER },
216233
{ FUNCTION_TRACE_ID.getName(), XRAY_TRACE_RESOLVER },
234+
{ CORRELATION_ID.getName(), CORRELATION_ID_RESOLVER },
217235
{ SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER },
218236
{ "region", REGION_RESOLVER },
219237
{ "account_id", ACCOUNT_ID_RESOLVER }

powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@
4545
"$resolver": "thread",
4646
"field": "name"
4747
},
48-
"cloud.provider" : "aws",
49-
"cloud.service.name" : "lambda",
50-
"cloud.region" : {
48+
"cloud.provider": "aws",
49+
"cloud.service.name": "lambda",
50+
"cloud.region": {
5151
"$resolver": "powertools",
5252
"field": "region"
5353
},
54-
"cloud.account.id" : {
54+
"cloud.account.id": {
5555
"$resolver": "powertools",
5656
"field": "account_id"
5757
},
@@ -83,7 +83,11 @@
8383
"$resolver": "powertools",
8484
"field": "xray_trace_id"
8585
},
86+
"correlation.id": {
87+
"$resolver": "powertools",
88+
"field": "correlation_id"
89+
},
8690
"": {
8791
"$resolver": "powertools"
8892
}
89-
}
93+
}

powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565
"$resolver": "powertools",
6666
"field": "xray_trace_id"
6767
},
68+
"correlation_id": {
69+
"$resolver": "powertools",
70+
"field": "correlation_id"
71+
},
6872
"": {
6973
"$resolver": "powertools"
7074
}

powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() {
9090
.contains(
9191
"\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}")
9292
.contains("\"message\":\"1212abcd\"")
93-
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"");
93+
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"")
94+
.contains("\"correlation_id\":\"1212abcd\"");
9495
// Reserved keys should be ignored
9596
PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> {
9697
assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\"");
@@ -122,7 +123,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() {
122123
.contains(
123124
"\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}")
124125
.contains("\"message\":\"1212abcd\"")
125-
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"");
126+
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"")
127+
.contains("\"correlation_id\":\"1212abcd\"");
126128

127129
// Reserved keys should be ignored
128130
PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package software.amazon.lambda.powertools.logging.logback;
1616

1717
import static java.nio.charset.StandardCharsets.UTF_8;
18+
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID;
1819
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN;
1920
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START;
2021
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE;
@@ -72,6 +73,7 @@ public class LambdaEcsEncoder extends EncoderBase<ILoggingEvent> {
7273
protected static final String FUNCTION_VERSION_ATTR_NAME = "faas.version";
7374
protected static final String FUNCTION_MEMORY_ATTR_NAME = "faas.memory";
7475
protected static final String FUNCTION_TRACE_ID_ATTR_NAME = "trace.id";
76+
protected static final String CORRELATION_ID_ATTR_NAME = "correlation.id";
7577

7678
protected static final String ECS_VERSION = "1.2.0";
7779
protected static final String CLOUD_PROVIDER = "aws";
@@ -156,6 +158,11 @@ private void serializeFunctionInfo(JsonSerializer serializer, String arn, Map<St
156158
serializer.writeStringField(FUNCTION_COLD_START_ATTR_NAME, mdcPropertyMap.get(FUNCTION_COLD_START.getName()));
157159
serializer.writeRaw(',');
158160
serializer.writeStringField(FUNCTION_TRACE_ID_ATTR_NAME, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName()));
161+
String correlationId = mdcPropertyMap.get(CORRELATION_ID.getName());
162+
if (correlationId != null) {
163+
serializer.writeRaw(',');
164+
serializer.writeStringField(CORRELATION_ID_ATTR_NAME, correlationId);
165+
}
159166
}
160167
}
161168

powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ void shouldNotLogFunctionInfo() {
102102

103103
// THEN
104104
assertThat(result).contains(
105-
"\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"false\"");
105+
"\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"false\"")
106+
.contains("\"correlation.id\":\"test-correlation-id\"");
106107

107108
// WHEN (includeFaasInfo = false)
108109
encoder.setIncludeFaasInfo(false);
@@ -175,6 +176,7 @@ private void setMDC() {
175176
MDC.put(PowertoolsLoggedFields.FUNCTION_COLD_START.getName(), "false");
176177
MDC.put(PowertoolsLoggedFields.SAMPLING_RATE.getName(), "0.2");
177178
MDC.put(PowertoolsLoggedFields.SERVICE.getName(), "Service");
179+
MDC.put(PowertoolsLoggedFields.CORRELATION_ID.getName(), "test-correlation-id");
178180
}
179181

180182
}

powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() {
135135
"\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}")
136136
.contains("\"message\":\"1212abcd\"")
137137
// Should auto-escape double quotes around id
138-
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"");
138+
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"")
139+
.contains("\"correlation_id\":\"1212abcd\"");
139140
// Reserved keys should be ignored
140141
PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> {
141142
assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\"");
@@ -168,7 +169,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() {
168169
"\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}")
169170
.contains("\"message\":\"1212abcd\"")
170171
// Should auto-escape double quotes around id
171-
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"");
172+
.contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"")
173+
.contains("\"correlation_id\":\"1212abcd\"");
172174
// Reserved keys should be ignored
173175
PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> {
174176
assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\"");

0 commit comments

Comments
 (0)