Skip to content

Commit c7b782d

Browse files
committed
feat(logging): add support for key-value pairs in LambdaEcsEncoder
1 parent 2b4b6a3 commit c7b782d

2 files changed

Lines changed: 73 additions & 5 deletions

File tree

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@
2323
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_REQUEST_ID;
2424
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID;
2525
import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION;
26-
import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeArguments;
27-
import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeMDCEntries;
28-
import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeTimestamp;
26+
import static software.amazon.lambda.powertools.logging.logback.JsonUtils.*;
2927

3028
import ch.qos.logback.classic.pattern.ThrowableHandlingConverter;
3129
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
@@ -34,8 +32,8 @@
3432
import ch.qos.logback.classic.spi.ThrowableProxy;
3533
import ch.qos.logback.core.encoder.EncoderBase;
3634
import java.io.IOException;
37-
import java.util.Arrays;
38-
import java.util.Map;
35+
import java.util.*;
36+
3937
import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor;
4038
import software.amazon.lambda.powertools.logging.internal.JsonSerializer;
4139

@@ -132,6 +130,8 @@ public byte[] encode(ILoggingEvent event) {
132130

133131
serializeMDCEntries(mdcPropertyMap, serializer);
134132

133+
serializeKeyValuePairs(event, serializer);
134+
135135
serializeArguments(event, serializer);
136136

137137
serializer.writeEndObject();
@@ -142,6 +142,13 @@ public byte[] encode(ILoggingEvent event) {
142142
return builder.toString().getBytes(UTF_8);
143143
}
144144

145+
private void serializeKeyValuePairs(ILoggingEvent event, JsonSerializer serializer) {
146+
Optional.ofNullable(event.getKeyValuePairs())
147+
.orElse(Collections.emptyList()).stream()
148+
.filter(Objects::nonNull)
149+
.forEach(kvp -> serializeKVPEntry(String.valueOf(kvp.key), kvp.value, serializer));
150+
}
151+
145152
private void serializeFunctionInfo(JsonSerializer serializer, String arn, Map<String, String> mdcPropertyMap) {
146153
if (includeFaasInfo) {
147154
serializer.writeRaw(',');

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.nio.file.NoSuchFileException;
2626
import java.nio.file.Paths;
2727
import java.nio.file.StandardOpenOption;
28+
import java.util.List;
2829
import java.util.concurrent.atomic.AtomicBoolean;
2930

3031
import org.junit.jupiter.api.AfterEach;
@@ -40,11 +41,14 @@
4041
import ch.qos.logback.classic.Logger;
4142
import ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter;
4243
import ch.qos.logback.classic.spi.LoggingEvent;
44+
import org.slf4j.event.KeyValuePair;
4345
import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor;
4446
import software.amazon.lambda.powertools.common.stubs.TestLambdaContext;
4547
import software.amazon.lambda.powertools.logging.PowertoolsLogging;
48+
import software.amazon.lambda.powertools.logging.argument.StructuredArguments;
4649
import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled;
4750
import software.amazon.lambda.powertools.logging.logback.LambdaEcsEncoder;
51+
import software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder;
4852

4953
@Order(3)
5054
class LambdaEcsEncoderTest {
@@ -179,4 +183,61 @@ private void setMDC() {
179183
MDC.put(PowertoolsLoggedFields.CORRELATION_ID.getName(), "test-correlation-id");
180184
}
181185

186+
@Test
187+
void shouldLogKeyValuePairs() {
188+
// GIVEN
189+
LambdaEcsEncoder encoder = new LambdaEcsEncoder();
190+
encoder.start();
191+
192+
Object[] arguments = {
193+
"argument_01",
194+
StructuredArguments.entry("structured_argument_01_retain", "retained"),
195+
StructuredArguments.entry("structured_argument_02_overwrite", "to_be_overwritten")
196+
};
197+
LoggingEvent keyValuePairsLoggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Key Value Pairs Test with argument: {}",
198+
null, arguments);
199+
200+
MDC.put("mdc_01_retain", "retained");
201+
MDC.put("mdc_02_overwrite", "to_be_overwritten");
202+
203+
keyValuePairsLoggingEvent.setKeyValuePairs(List.of(
204+
new KeyValuePair("key_01_string", "value_01"),
205+
new KeyValuePair("key_02_numeric", 2),
206+
new KeyValuePair("key_03_decimal", 2.333),
207+
new KeyValuePair("key_04_null", null),
208+
new KeyValuePair("", "value_05_empty_key"),
209+
new KeyValuePair(null, "value_06_null_key"),
210+
new KeyValuePair("key_07_boolean_true", true),
211+
new KeyValuePair("key_08_boolean_false", false),
212+
new KeyValuePair("mdc_02_overwrite", "overwritten_by_kvp"),
213+
new KeyValuePair("structured_argument_02_overwrite", "overwritten_by_kvp")
214+
));
215+
216+
// WHEN
217+
byte[] encoded = encoder.encode(keyValuePairsLoggingEvent);
218+
String result = new String(encoded, StandardCharsets.UTF_8);
219+
220+
// THEN
221+
assertThat(result)
222+
// Arguments
223+
.contains("Key Value Pairs Test with argument: argument_01")
224+
.contains("\"structured_argument_01_retain\":\"retained\"")
225+
// .doesNotContain("\"structured_argument_02_overwrite\":\"to_be_overwritten\"") TODO: Deduplication not implemented vor Arguments
226+
// MDC
227+
.contains("\"mdc_01_retain\":\"retained\"")
228+
// .doesNotContain("\"mdc_02_overwrite\":\"to_be_overwritten\"") TODO: Deduplication not implemented vor Arguments
229+
// Key Value Pairs
230+
.contains("\"key_01_string\":\"value_01\"")
231+
.contains("\"key_02_numeric\":2")
232+
.contains("\"key_03_decimal\":2.333")
233+
.contains("\"key_04_null\":null")
234+
.contains("\"\":\"value_05_empty_key\"")
235+
.contains("\"null\":\"value_06_null_key\"")
236+
.contains("\"key_07_boolean_true\":true")
237+
.contains("\"key_08_boolean_false\":false")
238+
.contains("\"mdc_02_overwrite\":\"overwritten_by_kvp\"")
239+
.contains("\"structured_argument_02_overwrite\":\"overwritten_by_kvp\"")
240+
;
241+
}
242+
182243
}

0 commit comments

Comments
 (0)