diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 46d054231..48e33d63a 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -42,7 +42,7 @@ The Powertools service name is used as the X-Ray namespace. This can be set usin ### Lambda handler -To enable Powertools tracing to your function add the `@Tracing annotation to your `handleRequest` method or on +To enable Powertools tracing to your function add the `@Tracing` annotation to your `handleRequest` method or on any method will capture the method as a separate subsegment automatically. You can optionally choose to customize segment name that appears in traces. @@ -81,6 +81,13 @@ segment name that appears in traces. } ``` +When using this `@Tracing` annotation, Utility performs these additional tasks to ease operations: + + * Creates a `ColdStart` annotation to easily filter traces that have had an initialization overhead. + * Creates a `Service` annotation if service parameter or `POWERTOOLS_SERVICE_NAME` is set. + * Captures any response, or full exceptions generated by the handler, and include as tracing metadata. + + By default, this annotation will automatically record method responses and exceptions. You can change the default behavior by setting the environment variables `POWERTOOLS_TRACER_CAPTURE_RESPONSE` and `POWERTOOLS_TRACER_CAPTURE_ERROR` as needed. Optionally, you can override behavior by different supported `captureMode` to record response, exception or both. diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java index a9c7a3965..1c6a166db 100644 --- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java @@ -50,6 +50,7 @@ public Object around(ProceedingJoinPoint pjp, if (placedOnHandlerMethod(pjp)) { segment.putAnnotation("ColdStart", isColdStart()); + segment.putAnnotation("Service", namespace(tracing)); } boolean captureResponse = captureResponse(tracing); diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java index 03c7b9110..415c501bf 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java @@ -104,12 +104,13 @@ void shouldCaptureNonHandlerMethodWithCustomSegmentName() { void shouldCaptureTraces() { requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .hasSize(1) @@ -123,12 +124,13 @@ void shouldCaptureTracesWithExceptionMetaData() { Throwable exception = catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .hasSize(1) @@ -144,12 +146,13 @@ void shouldCaptureTracesWithExceptionMetaData() { void shouldCaptureTracesForStream() throws IOException { streamHandler.handleRequest(new ByteArrayInputStream("test".getBytes()), new ByteArrayOutputStream(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "streamHandler"); assertThat(subsegment.getMetadata()) .hasSize(1) @@ -162,13 +165,13 @@ void shouldNotCaptureTracesNotEnabled() throws IOException { requestHandler = new PowerToolDisabled(); requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .isEmpty(); streamHandler = new PowerToolDisabledForStream(); streamHandler.handleRequest(new ByteArrayInputStream("test".getBytes()), new ByteArrayOutputStream(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .isEmpty(); } @@ -178,12 +181,13 @@ void shouldCaptureTracesWithNoMetadata() { requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "service_undefined"); assertThat(subsegment.getMetadata()) .isEmpty(); @@ -196,12 +200,13 @@ void shouldCaptureTracesForStreamWithNoMetadata() throws IOException { streamHandler.handleRequest(new ByteArrayInputStream("test".getBytes()), new ByteArrayOutputStream(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "service_undefined"); assertThat(subsegment.getMetadata()) .isEmpty(); @@ -214,12 +219,13 @@ void shouldCaptureTracesWithNoMetadataDeprecated() { requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "service_undefined"); assertThat(subsegment.getMetadata()) .isEmpty(); @@ -234,12 +240,13 @@ void shouldNotCaptureTracesIfDisabledViaEnvironmentVariable() { requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .isEmpty(); @@ -255,12 +262,13 @@ void shouldCaptureTracesIfExplicitlyEnabledAndEnvironmentVariableIsDisabled() { requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .hasSize(1) @@ -280,12 +288,13 @@ void shouldCaptureTracesIfExplicitlyEnabledBothAndEnvironmentVariableIsDisabled( requestHandler.handleRequest(new Object(), context); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .hasSize(1) @@ -303,12 +312,13 @@ void shouldNotCaptureTracesWithExceptionMetaDataIfDisabledViaEnvironmentVariable catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .isEmpty(); @@ -325,12 +335,13 @@ void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVari Throwable exception = catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) - .hasSize(1) - .containsEntry("ColdStart", true); + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) .hasSize(1)