From 6f3a6e0ad4a248001eed16fd6368e64bd2cc6473 Mon Sep 17 00:00:00 2001 From: Pankaj Agrawal Date: Fri, 25 Jun 2021 12:54:03 +0200 Subject: [PATCH 1/4] capture correlation ids --- pom.xml | 6 ++ powertools-logging/pom.xml | 5 + .../powertools/logging/CorrelationIdPath.java | 21 +++++ .../lambda/powertools/logging/Logging.java | 4 + .../powertools/logging/LoggingUtils.java | 10 ++ .../logging/internal/LambdaLoggingAspect.java | 91 +++++++++++++++++-- .../PowerLogToolAlbCorrelationId.java | 40 ++++++++ ...LogToolApiGatewayHttpApiCorrelationId.java | 42 +++++++++ ...LogToolApiGatewayRestApiCorrelationId.java | 40 ++++++++ .../PowerLogToolAutoCorrelationId.java | 42 +++++++++ .../internal/LambdaLoggingAspectTest.java | 54 +++++++++++ .../src/test/resources/albEvent.json | 28 ++++++ .../resources/apiGatewayProxyEventV1.json | 32 +++++++ .../resources/apiGatewayProxyEventV2.json | 33 +++++++ 14 files changed, 440 insertions(+), 8 deletions(-) create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java create mode 100644 powertools-logging/src/test/resources/albEvent.json create mode 100644 powertools-logging/src/test/resources/apiGatewayProxyEventV1.json create mode 100644 powertools-logging/src/test/resources/apiGatewayProxyEventV2.json diff --git a/pom.xml b/pom.xml index e5e9a0611..fe7cbba9d 100644 --- a/pom.xml +++ b/pom.xml @@ -226,6 +226,12 @@ aspectjtools ${aspectj.version} + + com.amazonaws + aws-lambda-java-tests + 1.0.2 + test + diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 080b4e69d..1cd4ee50b 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -112,6 +112,11 @@ aws-lambda-java-events test + + com.amazonaws + aws-lambda-java-tests + test + org.skyscreamer jsonassert diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java new file mode 100644 index 000000000..6a1e1dc65 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java @@ -0,0 +1,21 @@ +package software.amazon.lambda.powertools.logging; + +public enum CorrelationIdPath { + API_GATEWAY_REST("/requestContext/requestId"), + API_GATEWAY_HTTP("/requestContext/requestId"), + APPLICATION_LOAD_BALANCER("/headers/x-amzn-trace-id"), + EVENT_BRIDGE("/id"), + AUTO_DETECT(""), + DISABLED(""); + + private final String path; + + + CorrelationIdPath(String path) { + this.path = path; + } + + public String getPath() { + return path; + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java index 97ce74617..e01d799ef 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java @@ -18,6 +18,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.DISABLED; + /** * {@code Logging} is used to signal that the annotated method should be * extended with Logging functionality. @@ -67,4 +69,6 @@ boolean logEvent() default false; double samplingRate() default 0; + + CorrelationIdPath correlationIdPath() default DISABLED; } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java index 418ae584b..29f983cb2 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java @@ -43,6 +43,7 @@ public static void appendKey(String key, String value) { } + /** * Appends additional key and value to each log entry made. Duplicate values * for the same key will be replaced with the latest. @@ -72,6 +73,15 @@ public static void removeKeys(String... keys) { ThreadContext.removeAll(asList(keys)); } + /** + * Sets correlation id attribute on the logs. + * + * @param value The value of the correlation id + */ + public static void setCorrelationId(String value) { + ThreadContext.put("correlation_id", value); + } + /** * Sets the instance of ObjectMapper object which is used for serialising event when * {@code @Logging(logEvent = true)}. diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 17b6fa021..94233029b 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -19,11 +19,16 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.util.Arrays; import java.util.Map; import java.util.Optional; import java.util.Random; +import java.util.function.Consumer; +import java.util.function.Predicate; +import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -34,7 +39,9 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; +import software.amazon.lambda.powertools.logging.CorrelationIdPath; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Optional.empty; @@ -47,6 +54,8 @@ import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler; import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnStreamHandler; import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName; +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.AUTO_DETECT; +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.DISABLED; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKey; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKeys; import static software.amazon.lambda.powertools.logging.LoggingUtils.objectMapper; @@ -94,6 +103,10 @@ public Object around(ProceedingJoinPoint pjp, proceedArgs = logEvent(pjp); } + if (logging.correlationIdPath() != DISABLED) { + proceedArgs = captureCorrelationId(logging.correlationIdPath(), pjp); + } + Object proceed = pjp.proceed(proceedArgs); coldStartDone(); @@ -160,18 +173,69 @@ private Object[] logEvent(final ProceedingJoinPoint pjp) { return args; } - private Object[] logFromInputStream(final ProceedingJoinPoint pjp) { + private Object[] captureCorrelationId(final CorrelationIdPath correlationIdPath, + final ProceedingJoinPoint pjp) { Object[] args = pjp.getArgs(); + if (isHandlerMethod(pjp)) { + if (placedOnRequestHandler(pjp)) { + Object arg = pjp.getArgs()[0]; + JsonNode jsonNode = objectMapper().valueToTree(arg); - try (ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out, UTF_8); - InputStreamReader reader = new InputStreamReader((InputStream) pjp.getArgs()[0], UTF_8)) { + setCorrelationIdFromNode(correlationIdPath, pjp, jsonNode); - IOUtils.copy(reader, writer); - writer.flush(); - byte[] bytes = out.toByteArray(); - args[0] = new ByteArrayInputStream(bytes); + return args; + } + + if (placedOnStreamHandler(pjp)) { + try { + byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); + JsonNode jsonNode = objectMapper().readTree(bytes); + args[0] = new ByteArrayInputStream(bytes); + + setCorrelationIdFromNode(correlationIdPath, pjp, jsonNode); + + return args; + } catch (IOException e) { + Logger log = logger(pjp); + log.warn("Failed to capture correlation id on event from supplied input stream.", e); + } + } + } + + return args; + } + + private void setCorrelationIdFromNode(CorrelationIdPath correlationIdPath, ProceedingJoinPoint pjp, JsonNode jsonNode) { + if (correlationIdPath == AUTO_DETECT) { + autoDetect(pjp, jsonNode); + } else { + JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath.getPath())); + LoggingUtils.setCorrelationId(node.asText()); + } + } + + private void autoDetect(ProceedingJoinPoint pjp, + JsonNode jsonNode) { + Arrays.stream(CorrelationIdPath.values()) + .filter(path -> path != AUTO_DETECT && path != DISABLED) + .forEach(correlationIdPath1 -> { + JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath1.getPath())); + String asText = node.asText(); + + if (null != asText && !asText.isEmpty()) { + logger(pjp).debug("Auto detected correlation id from event type: {}", correlationIdPath1); + LoggingUtils.setCorrelationId(asText); + } + }); + } + + + private Object[] logFromInputStream(final ProceedingJoinPoint pjp) { + Object[] args = pjp.getArgs(); + try { + byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); + args[0] = new ByteArrayInputStream(bytes); Logger log = logger(pjp); asJson(pjp, objectMapper().readValue(bytes, Map.class)) @@ -185,6 +249,17 @@ private Object[] logFromInputStream(final ProceedingJoinPoint pjp) { return args; } + private byte[] bytesFromInputStreamSafely(final InputStream inputStream) throws IOException { + try (ByteArrayOutputStream out = new ByteArrayOutputStream(); + InputStreamReader reader = new InputStreamReader(inputStream)) { + OutputStreamWriter writer = new OutputStreamWriter(out, UTF_8); + + IOUtils.copy(reader, writer); + writer.flush(); + return out.toByteArray(); + } + } + private Optional asJson(final ProceedingJoinPoint pjp, final Object target) { try { diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java new file mode 100644 index 000000000..e4bb5560d --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.logging.Logging; + +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.APPLICATION_LOAD_BALANCER; + +public class PowerLogToolAlbCorrelationId implements RequestHandler { + private final Logger LOG = LogManager.getLogger(PowerLogToolAlbCorrelationId.class); + + @Override + @Logging(correlationIdPath = APPLICATION_LOAD_BALANCER) + public Object handleRequest(ApplicationLoadBalancerRequestEvent input, Context context) { + LOG.info("Test event"); + LOG.debug("Test debug event"); + return null; + } + + @Logging + public void anotherMethod() { + System.out.println("test"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java new file mode 100644 index 000000000..00ad0ff54 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java @@ -0,0 +1,42 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.logging.Logging; + +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.API_GATEWAY_HTTP; +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.API_GATEWAY_REST; + +public class PowerLogToolApiGatewayHttpApiCorrelationId implements RequestHandler { + private final Logger LOG = LogManager.getLogger(PowerLogToolApiGatewayHttpApiCorrelationId.class); + + @Override + @Logging(correlationIdPath = API_GATEWAY_HTTP) + public Object handleRequest(APIGatewayV2HTTPEvent input, Context context) { + LOG.info("Test event"); + LOG.debug("Test debug event"); + return null; + } + + @Logging + public void anotherMethod() { + System.out.println("test"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java new file mode 100644 index 000000000..89a1d8761 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.logging.Logging; + +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.API_GATEWAY_REST; + +public class PowerLogToolApiGatewayRestApiCorrelationId implements RequestHandler { + private final Logger LOG = LogManager.getLogger(PowerLogToolApiGatewayRestApiCorrelationId.class); + + @Override + @Logging(correlationIdPath = API_GATEWAY_REST) + public Object handleRequest(APIGatewayProxyRequestEvent input, Context context) { + LOG.info("Test event"); + LOG.debug("Test debug event"); + return null; + } + + @Logging + public void anotherMethod() { + System.out.println("test"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java new file mode 100644 index 000000000..5f4e54ac4 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java @@ -0,0 +1,42 @@ +/* + * Copyright 2020 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.logging.Logging; + +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.APPLICATION_LOAD_BALANCER; +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.AUTO_DETECT; +import static software.amazon.lambda.powertools.logging.CorrelationIdPath.DISABLED; + +public class PowerLogToolAutoCorrelationId implements RequestHandler { + private final Logger LOG = LogManager.getLogger(PowerLogToolAutoCorrelationId.class); + + @Override + @Logging(correlationIdPath = AUTO_DETECT) + public Object handleRequest(ApplicationLoadBalancerRequestEvent input, Context context) { + LOG.info("Test event"); + LOG.debug("Test debug event"); + return null; + } + + @Logging + public void anotherMethod() { + System.out.println("test"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 526c9bac8..dfa8aab7a 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -30,7 +30,11 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; +import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; +import com.amazonaws.services.lambda.runtime.tests.annotations.Event; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.logging.log4j.Level; @@ -38,10 +42,15 @@ import org.json.JSONException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; import org.mockito.MockedStatic; import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.core.internal.SystemWrapper; +import software.amazon.lambda.powertools.logging.handlers.PowerLogToolAlbCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayHttpApiCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayRestApiCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowerLogToolAutoCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabledForStream; import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabled; @@ -248,6 +257,51 @@ void shouldLogxRayTraceIdEnvVarSet() { } } + @ParameterizedTest + @Event(value = "apiGatewayProxyEventV1.json", type = APIGatewayProxyRequestEvent.class) + void shouldLogCorrelationIdOnAPIGatewayProxyRequestEvent(APIGatewayProxyRequestEvent event) { + RequestHandler handler = new PowerLogToolApiGatewayRestApiCorrelationId(); + handler.handleRequest(event, context); + + assertThat(ThreadContext.getImmutableContext()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("correlation_id", event.getRequestContext().getRequestId()); + } + + @ParameterizedTest + @Event(value = "apiGatewayProxyEventV2.json", type = APIGatewayV2HTTPEvent.class) + void shouldLogCorrelationIdOnAPIGatewayV2HTTPEvent(APIGatewayV2HTTPEvent event) { + RequestHandler handler = new PowerLogToolApiGatewayHttpApiCorrelationId(); + handler.handleRequest(event, context); + + assertThat(ThreadContext.getImmutableContext()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("correlation_id", event.getRequestContext().getRequestId()); + } + + @ParameterizedTest + @Event(value = "albEvent.json", type = ApplicationLoadBalancerRequestEvent.class) + void shouldLogCorrelationIdOnALBEvent(ApplicationLoadBalancerRequestEvent event) { + RequestHandler handler = new PowerLogToolAlbCorrelationId(); + handler.handleRequest(event, context); + + assertThat(ThreadContext.getImmutableContext()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("correlation_id", event.getHeaders().get("x-amzn-trace-id")); + } + + @ParameterizedTest + @Event(value = "albEvent.json", type = ApplicationLoadBalancerRequestEvent.class) + void shouldLogCorrelationIdOnAutoDetect(ApplicationLoadBalancerRequestEvent event) { + RequestHandler handler = new PowerLogToolAutoCorrelationId(); + handler.handleRequest(event, context); + + assertThat(ThreadContext.getImmutableContext()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("correlation_id", event.getHeaders().get("x-amzn-trace-id")); + } + + private void setupContext() { when(context.getFunctionName()).thenReturn("testFunction"); when(context.getInvokedFunctionArn()).thenReturn("testArn"); diff --git a/powertools-logging/src/test/resources/albEvent.json b/powertools-logging/src/test/resources/albEvent.json new file mode 100644 index 000000000..83f847ec8 --- /dev/null +++ b/powertools-logging/src/test/resources/albEvent.json @@ -0,0 +1,28 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" + } + }, + "httpMethod": "GET", + "path": "/lambda", + "queryStringParameters": { + "query": "1234ABCD" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "accept-encoding": "gzip", + "accept-language": "en-US,en;q=0.9", + "connection": "keep-alive", + "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", + "x-forwarded-for": "72.12.164.125", + "x-forwarded-port": "80", + "x-forwarded-proto": "http", + "x-imforwards": "20" + }, + "body": "", + "isBase64Encoded": false +} \ No newline at end of file diff --git a/powertools-logging/src/test/resources/apiGatewayProxyEventV1.json b/powertools-logging/src/test/resources/apiGatewayProxyEventV1.json new file mode 100644 index 000000000..c53b6f6b5 --- /dev/null +++ b/powertools-logging/src/test/resources/apiGatewayProxyEventV1.json @@ -0,0 +1,32 @@ +{ + "resource": "/", + "path": "/", + "httpMethod": "GET", + "requestContext": { + "requestId": "77375676-xmpl-4b79-853a-f982474efe18", + "resourcePath": "/", + "httpMethod": "GET", + "path": "/Prod/" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "accept-encoding": "gzip, deflate, br", + "Host": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36", + "X-Amzn-Trace-Id": "Root=1-5e66d96f-7491f09xmpl79d18acf3d050" + }, + "multiValueHeaders": { + "accept": [ + "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" + ], + "accept-encoding": [ + "gzip, deflate, br" + ] + }, + "queryStringParameters": null, + "multiValueQueryStringParameters": null, + "pathParameters": null, + "stageVariables": null, + "body": null, + "isBase64Encoded": false +} \ No newline at end of file diff --git a/powertools-logging/src/test/resources/apiGatewayProxyEventV2.json b/powertools-logging/src/test/resources/apiGatewayProxyEventV2.json new file mode 100644 index 000000000..720898aeb --- /dev/null +++ b/powertools-logging/src/test/resources/apiGatewayProxyEventV2.json @@ -0,0 +1,33 @@ +{ + "version": "2.0", + "routeKey": "ANY /nodejs-apig-function-1G3XMPLZXVXYI", + "rawPath": "/default/nodejs-apig-function-1G3XMPLZXVXYI", + "rawQueryString": "", + "cookies": [ + "s_fid=7AABXMPL1AFD9BBF-0643XMPL09956DE2", + "regStatus=pre-register" + ], + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "accept-encoding": "gzip, deflate, br" + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "r3pmxmplak", + "domainName": "r3pmxmplak.execute-api.us-east-2.amazonaws.com", + "domainPrefix": "r3pmxmplak", + "http": { + "method": "GET", + "path": "/default/nodejs-apig-function-1G3XMPLZXVXYI", + "protocol": "HTTP/1.1", + "sourceIp": "205.255.255.176", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36" + }, + "requestId": "JKJaXmPLvHcESHA=", + "routeKey": "ANY /nodejs-apig-function-1G3XMPLZXVXYI", + "stage": "default", + "time": "10/Mar/2020:05:16:23 +0000", + "timeEpoch": 1583817383220 + }, + "isBase64Encoded": true +} \ No newline at end of file From dd3f03b4c5c3bdea8888d9052749879a7079e8a4 Mon Sep 17 00:00:00 2001 From: Pankaj Agrawal Date: Fri, 25 Jun 2021 13:43:53 +0200 Subject: [PATCH 2/4] chore: docs and javadocs update --- .../powertools/logging/CorrelationIdPath.java | 23 +++++++++++++++++++ .../lambda/powertools/logging/Logging.java | 3 +++ .../logging/internal/LambdaLoggingAspect.java | 8 ++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java index 6a1e1dc65..8810a7cc3 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java @@ -1,11 +1,34 @@ package software.amazon.lambda.powertools.logging; +/** + * Supported Event types from which Correlation ID can be extracted + */ public enum CorrelationIdPath { + /** + * To use when function is expecting API Gateway Rest API Request event + */ API_GATEWAY_REST("/requestContext/requestId"), + /** + * To use when function is expecting API Gateway HTTP API Request event + */ API_GATEWAY_HTTP("/requestContext/requestId"), + /** + * To use when function is expecting Application Load balancer Request event + */ APPLICATION_LOAD_BALANCER("/headers/x-amzn-trace-id"), + /** + * To use when function is expecting Event Bridge Request event + */ EVENT_BRIDGE("/id"), + /** + * To use when function is expecting any of the supported event types to automatically + * extract the correlation id. When running in this mode, if its unable to find any of the + * supported types, capturing of correlation id will not be done. + */ AUTO_DETECT(""), + /** + * To use when you dont want to extract correlation id. + */ DISABLED(""); private final String path; diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java index e01d799ef..312c8924d 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java @@ -70,5 +70,8 @@ double samplingRate() default 0; + /** + * Type of Event from where to extract correlation id from. + */ CorrelationIdPath correlationIdPath() default DISABLED; } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 94233029b..83e08bd15 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -210,7 +210,13 @@ private void setCorrelationIdFromNode(CorrelationIdPath correlationIdPath, Proce autoDetect(pjp, jsonNode); } else { JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath.getPath())); - LoggingUtils.setCorrelationId(node.asText()); + + String asText = node.asText(); + if (null != asText && !asText.isEmpty()) { + LoggingUtils.setCorrelationId(asText); + } else { + logger(pjp).debug("Unable to extract any correlation id. Is your function expecting supported event type?"); + } } } From 2dffc2fad21ce2fd2ce521a28576a38f68e90068 Mon Sep 17 00:00:00 2001 From: Pankaj Agrawal Date: Fri, 25 Jun 2021 14:25:35 +0200 Subject: [PATCH 3/4] support any Json Pointer path --- .../powertools/logging/CorrelationIdPath.java | 44 ------------------- .../logging/CorrelationIdPathConstants.java | 23 ++++++++++ .../lambda/powertools/logging/Logging.java | 7 ++- .../logging/internal/LambdaLoggingAspect.java | 44 ++++--------------- .../PowerLogToolAlbCorrelationId.java | 9 ++-- ...LogToolApiGatewayHttpApiCorrelationId.java | 9 +--- ...LogToolApiGatewayRestApiCorrelationId.java | 7 +-- .../PowerLogToolAutoCorrelationId.java | 42 ------------------ .../internal/LambdaLoggingAspectTest.java | 13 ------ 9 files changed, 40 insertions(+), 158 deletions(-) delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java delete mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java deleted file mode 100644 index 8810a7cc3..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPath.java +++ /dev/null @@ -1,44 +0,0 @@ -package software.amazon.lambda.powertools.logging; - -/** - * Supported Event types from which Correlation ID can be extracted - */ -public enum CorrelationIdPath { - /** - * To use when function is expecting API Gateway Rest API Request event - */ - API_GATEWAY_REST("/requestContext/requestId"), - /** - * To use when function is expecting API Gateway HTTP API Request event - */ - API_GATEWAY_HTTP("/requestContext/requestId"), - /** - * To use when function is expecting Application Load balancer Request event - */ - APPLICATION_LOAD_BALANCER("/headers/x-amzn-trace-id"), - /** - * To use when function is expecting Event Bridge Request event - */ - EVENT_BRIDGE("/id"), - /** - * To use when function is expecting any of the supported event types to automatically - * extract the correlation id. When running in this mode, if its unable to find any of the - * supported types, capturing of correlation id will not be done. - */ - AUTO_DETECT(""), - /** - * To use when you dont want to extract correlation id. - */ - DISABLED(""); - - private final String path; - - - CorrelationIdPath(String path) { - this.path = path; - } - - public String getPath() { - return path; - } -} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java new file mode 100644 index 000000000..e0d24b8a5 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java @@ -0,0 +1,23 @@ +package software.amazon.lambda.powertools.logging; + +/** + * Supported Event types from which Correlation ID can be extracted + */ +public class CorrelationIdPathConstants { + /** + * To use when function is expecting API Gateway Rest API Request event + */ + public static final String API_GATEWAY_REST = "/requestContext/requestId"; + /** + * To use when function is expecting API Gateway HTTP API Request event + */ + public static final String API_GATEWAY_HTTP = "/requestContext/requestId"; + /** + * To use when function is expecting Application Load balancer Request event + */ + public static final String APPLICATION_LOAD_BALANCER = "/headers/x-amzn-trace-id"; + /** + * To use when function is expecting Event Bridge Request event + */ + public static final String EVENT_BRIDGE = "/id"; +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java index 312c8924d..a5c714bd3 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java @@ -18,8 +18,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.DISABLED; - /** * {@code Logging} is used to signal that the annotated method should be * extended with Logging functionality. @@ -71,7 +69,8 @@ double samplingRate() default 0; /** - * Type of Event from where to extract correlation id from. + * Json Pointer path to extract correlation id from. + * @see */ - CorrelationIdPath correlationIdPath() default DISABLED; + String correlationIdPath() default ""; } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 83e08bd15..1710a94f6 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -19,12 +19,9 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; -import java.util.Arrays; import java.util.Map; import java.util.Optional; import java.util.Random; -import java.util.function.Consumer; -import java.util.function.Predicate; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonProcessingException; @@ -39,7 +36,6 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; -import software.amazon.lambda.powertools.logging.CorrelationIdPath; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.logging.LoggingUtils; @@ -54,8 +50,6 @@ import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler; import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnStreamHandler; import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.AUTO_DETECT; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.DISABLED; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKey; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKeys; import static software.amazon.lambda.powertools.logging.LoggingUtils.objectMapper; @@ -103,7 +97,7 @@ public Object around(ProceedingJoinPoint pjp, proceedArgs = logEvent(pjp); } - if (logging.correlationIdPath() != DISABLED) { + if (!logging.correlationIdPath().isEmpty()) { proceedArgs = captureCorrelationId(logging.correlationIdPath(), pjp); } @@ -173,7 +167,7 @@ private Object[] logEvent(final ProceedingJoinPoint pjp) { return args; } - private Object[] captureCorrelationId(final CorrelationIdPath correlationIdPath, + private Object[] captureCorrelationId(final String correlationIdPath, final ProceedingJoinPoint pjp) { Object[] args = pjp.getArgs(); if (isHandlerMethod(pjp)) { @@ -205,37 +199,17 @@ private Object[] captureCorrelationId(final CorrelationIdPath correlationIdPath, return args; } - private void setCorrelationIdFromNode(CorrelationIdPath correlationIdPath, ProceedingJoinPoint pjp, JsonNode jsonNode) { - if (correlationIdPath == AUTO_DETECT) { - autoDetect(pjp, jsonNode); - } else { - JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath.getPath())); + private void setCorrelationIdFromNode(String correlationIdPath, ProceedingJoinPoint pjp, JsonNode jsonNode) { + JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath)); - String asText = node.asText(); - if (null != asText && !asText.isEmpty()) { - LoggingUtils.setCorrelationId(asText); - } else { - logger(pjp).debug("Unable to extract any correlation id. Is your function expecting supported event type?"); - } + String asText = node.asText(); + if (null != asText && !asText.isEmpty()) { + LoggingUtils.setCorrelationId(asText); + } else { + logger(pjp).debug("Unable to extract any correlation id. Is your function expecting supported event type?"); } } - private void autoDetect(ProceedingJoinPoint pjp, - JsonNode jsonNode) { - Arrays.stream(CorrelationIdPath.values()) - .filter(path -> path != AUTO_DETECT && path != DISABLED) - .forEach(correlationIdPath1 -> { - JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath1.getPath())); - String asText = node.asText(); - - if (null != asText && !asText.isEmpty()) { - logger(pjp).debug("Auto detected correlation id from event type: {}", correlationIdPath1); - LoggingUtils.setCorrelationId(asText); - } - }); - } - - private Object[] logFromInputStream(final ProceedingJoinPoint pjp) { Object[] args = pjp.getArgs(); diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java index e4bb5560d..125c13e26 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAlbCorrelationId.java @@ -18,9 +18,11 @@ import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.logging.CorrelationIdPathConstants; import software.amazon.lambda.powertools.logging.Logging; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.APPLICATION_LOAD_BALANCER; +import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.API_GATEWAY_REST; +import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.APPLICATION_LOAD_BALANCER; public class PowerLogToolAlbCorrelationId implements RequestHandler { private final Logger LOG = LogManager.getLogger(PowerLogToolAlbCorrelationId.class); @@ -32,9 +34,4 @@ public Object handleRequest(ApplicationLoadBalancerRequestEvent input, Context c LOG.debug("Test debug event"); return null; } - - @Logging - public void anotherMethod() { - System.out.println("test"); - } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java index 00ad0ff54..4e40e0f97 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java @@ -15,14 +15,12 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.API_GATEWAY_HTTP; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.API_GATEWAY_REST; +import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.API_GATEWAY_HTTP; public class PowerLogToolApiGatewayHttpApiCorrelationId implements RequestHandler { private final Logger LOG = LogManager.getLogger(PowerLogToolApiGatewayHttpApiCorrelationId.class); @@ -34,9 +32,4 @@ public Object handleRequest(APIGatewayV2HTTPEvent input, Context context) { LOG.debug("Test debug event"); return null; } - - @Logging - public void anotherMethod() { - System.out.println("test"); - } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java index 89a1d8761..e3cadaf84 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java @@ -20,7 +20,7 @@ import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.API_GATEWAY_REST; +import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.API_GATEWAY_REST; public class PowerLogToolApiGatewayRestApiCorrelationId implements RequestHandler { private final Logger LOG = LogManager.getLogger(PowerLogToolApiGatewayRestApiCorrelationId.class); @@ -32,9 +32,4 @@ public Object handleRequest(APIGatewayProxyRequestEvent input, Context context) LOG.debug("Test debug event"); return null; } - - @Logging - public void anotherMethod() { - System.out.println("test"); - } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java deleted file mode 100644 index 5f4e54ac4..000000000 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolAutoCorrelationId.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2020 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -package software.amazon.lambda.powertools.logging.handlers; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.lambda.powertools.logging.Logging; - -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.APPLICATION_LOAD_BALANCER; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.AUTO_DETECT; -import static software.amazon.lambda.powertools.logging.CorrelationIdPath.DISABLED; - -public class PowerLogToolAutoCorrelationId implements RequestHandler { - private final Logger LOG = LogManager.getLogger(PowerLogToolAutoCorrelationId.class); - - @Override - @Logging(correlationIdPath = AUTO_DETECT) - public Object handleRequest(ApplicationLoadBalancerRequestEvent input, Context context) { - LOG.info("Test event"); - LOG.debug("Test debug event"); - return null; - } - - @Logging - public void anotherMethod() { - System.out.println("test"); - } -} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index dfa8aab7a..8c9c9b67b 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -50,7 +50,6 @@ import software.amazon.lambda.powertools.logging.handlers.PowerLogToolAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayHttpApiCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayRestApiCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolAutoCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabledForStream; import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabled; @@ -290,18 +289,6 @@ void shouldLogCorrelationIdOnALBEvent(ApplicationLoadBalancerRequestEvent event) .containsEntry("correlation_id", event.getHeaders().get("x-amzn-trace-id")); } - @ParameterizedTest - @Event(value = "albEvent.json", type = ApplicationLoadBalancerRequestEvent.class) - void shouldLogCorrelationIdOnAutoDetect(ApplicationLoadBalancerRequestEvent event) { - RequestHandler handler = new PowerLogToolAutoCorrelationId(); - handler.handleRequest(event, context); - - assertThat(ThreadContext.getImmutableContext()) - .hasSize(EXPECTED_CONTEXT_SIZE + 1) - .containsEntry("correlation_id", event.getHeaders().get("x-amzn-trace-id")); - } - - private void setupContext() { when(context.getFunctionName()).thenReturn("testFunction"); when(context.getInvokedFunctionArn()).thenReturn("testArn"); From 4fa0436fb41071847754a0cf949296aa255de46b Mon Sep 17 00:00:00 2001 From: Pankaj Agrawal Date: Fri, 25 Jun 2021 14:35:45 +0200 Subject: [PATCH 4/4] docs: correlation id extraction --- docs/core/logging.md | 99 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/docs/core/logging.md b/docs/core/logging.md index 37aa1e0a9..f0ca99845 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -123,6 +123,105 @@ to customise what is logged. } ``` +## Setting a Correlation ID + +You can set a Correlation ID using `correlationIdPath` attribute by passing a [JSON Pointer expression](https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03){target="_blank"}. + +=== "App.java" + + ```java hl_lines="8" + /** + * Handler for requests to Lambda function. + */ + public class App implements RequestHandler { + + Logger log = LogManager.getLogger(); + + @Logging(correlationIdPath = "/headers/my_request_id_header") + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + ... + log.info("Collecting payment") + ... + } + } + ``` +=== "Example Event" + + ```json hl_lines="3" + { + "headers": { + "my_request_id_header": "correlation_id_value" + } + } + ``` + +=== "Example CloudWatch Logs excerpt" + + ```json hl_lines="11" + { + "level": "INFO", + "message": "Collecting payment", + "timestamp": "2021-05-03 11:47:12,494+0200", + "service": "payment", + "coldStart": true, + "functionName": "test", + "functionMemorySize": 128, + "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", + "lambda_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", + "correlation_id": "correlation_id_value" + } + ``` +We provide [built-in JSON Pointer expression](https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03){target="_blank"} +for known event sources, where either a request ID or X-Ray Trace ID are present. + +=== "App.java" + + ```java hl_lines="10" + import software.amazon.lambda.powertools.logging.CorrelationIdPathConstants; + + /** + * Handler for requests to Lambda function. + */ + public class App implements RequestHandler { + + Logger log = LogManager.getLogger(); + + @Logging(correlationIdPath = CorrelationIdPathConstants.API_GATEWAY_REST) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + ... + log.info("Collecting payment") + ... + } + } + ``` + +=== "Example Event" + + ```json hl_lines="3" + { + "requestContext": { + "requestId": "correlation_id_value" + } + } + ``` + +=== "Example CloudWatch Logs excerpt" + + ```json hl_lines="11" + { + "level": "INFO", + "message": "Collecting payment", + "timestamp": "2021-05-03 11:47:12,494+0200", + "service": "payment", + "coldStart": true, + "functionName": "test", + "functionMemorySize": 128, + "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", + "lambda_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", + "correlation_id": "correlation_id_value" + } + ``` + ## Appending additional keys You can append your own keys to your existing logs via `appendKey`.