From 7c280767674371a6caf5d6cbd382d3f5b2d9a6e9 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 11:40:55 +0200 Subject: [PATCH 1/9] Clarify how to mock the Lambda context in unit tests for Metrics utility. --- docs/core/metrics.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 31079a76e..57d134c31 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -558,10 +558,11 @@ If you would like to suppress metrics output during your unit tests, you can use When unit testing your code, you can run assertions against the output generated by the `Metrics` Singleton. For the `EmfMetricsLogger`, you can assert the generated JSON blob following the [CloudWatch EMF specification](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html) against your expected output. -Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. +Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. Note that it is important to mock the Lambda `Context` with realistic values so that the metrics have valid metadata and dimensions during unit tests. -```java hl_lines="23 28 33 50-55" +```java hl_lines="26-27 35 37-42 47 63-68" import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -571,6 +572,9 @@ import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -578,10 +582,13 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +@ExtendWith(MockitoExtension.class) class MetricsTestExample { + @Mock + Context lambdaContext; + private final PrintStream standardOut = System.out; private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -589,6 +596,13 @@ class MetricsTestExample { @BeforeEach void setUp() { System.setOut(new PrintStream(outputStreamCaptor)); + + // Mock a minimal realistic Lambda context. These values are used in metadata and dimensions by the Metrics utility. + when(lambdaContext.getAwsRequestId()).thenReturn("test-request-id"); + when(lambdaContext.getFunctionName()).thenReturn("test-function"); + when(lambdaContext.getFunctionVersion()).thenReturn("test-version"); + when(lambdaContext.getInvokedFunctionArn()).thenReturn("test-arn"); + when(lambdaContext.getMemoryLimitInMB()).thenReturn(128); } @AfterEach @@ -600,11 +614,10 @@ class MetricsTestExample { void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { // Given RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); Map input = new HashMap<>(); // When - handler.handleRequest(input, context); + handler.handleRequest(input, lambdaContext); // Then String emfOutput = outputStreamCaptor.toString().trim(); From 7cea2a69dfcdd4ae60dfdbef3d1c927ec00fde38 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 11:58:49 +0200 Subject: [PATCH 2/9] Revert when() mocking in documentation. --- docs/core/metrics.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 57d134c31..980fc8680 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -558,11 +558,10 @@ If you would like to suppress metrics output during your unit tests, you can use When unit testing your code, you can run assertions against the output generated by the `Metrics` Singleton. For the `EmfMetricsLogger`, you can assert the generated JSON blob following the [CloudWatch EMF specification](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html) against your expected output. -Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. Note that it is important to mock the Lambda `Context` with realistic values so that the metrics have valid metadata and dimensions during unit tests. +Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. -```java hl_lines="26-27 35 37-42 47 63-68" +```java hl_lines="34 39 55-60" import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -596,13 +595,6 @@ class MetricsTestExample { @BeforeEach void setUp() { System.setOut(new PrintStream(outputStreamCaptor)); - - // Mock a minimal realistic Lambda context. These values are used in metadata and dimensions by the Metrics utility. - when(lambdaContext.getAwsRequestId()).thenReturn("test-request-id"); - when(lambdaContext.getFunctionName()).thenReturn("test-function"); - when(lambdaContext.getFunctionVersion()).thenReturn("test-version"); - when(lambdaContext.getInvokedFunctionArn()).thenReturn("test-arn"); - when(lambdaContext.getMemoryLimitInMB()).thenReturn(128); } @AfterEach From e7de05c1d5fb84ce3d6b6104d9701201767b160d Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 12:15:19 +0200 Subject: [PATCH 3/9] Avoid metrics from raising an exception when using plain mocked Lambda context. --- powertools-metrics/pom.xml | 19 ++++ .../metrics/internal/EmfMetricsLogger.java | 2 +- .../metrics/internal/LambdaMetricsAspect.java | 5 +- .../metrics/RequestHandlerTest.java | 101 ++++++++++++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 4bccab505..b90506c25 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -105,6 +105,11 @@ assertj-core test + + org.mockito + mockito-junit-jupiter + test + software.amazon.lambda powertools-common @@ -135,6 +140,13 @@ generate-graalvm-files + + + org.mockito + mockito-subclass + test + + @@ -154,6 +166,13 @@ graalvm-native + + + org.mockito + mockito-subclass + test + + diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java index 2f6f9e689..c9651585f 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -204,7 +204,7 @@ public void captureColdStartMetric(Context context, } // Add request ID from context if available - if (context != null) { + if (context != null && context.getAwsRequestId() != null) { coldStartLogger.putProperty(REQUEST_ID_PROPERTY, context.getAwsRequestId()); } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java index b214d7c52..a05ce9568 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java @@ -113,7 +113,10 @@ private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetr } Metrics metricsInstance = MetricsFactory.getMetricsInstance(); - metricsInstance.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); + // This can be null e.g. during unit tests when mocking the Lambda context + if (extractedContext.getAwsRequestId() != null) { + metricsInstance.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); + } // Only capture cold start metrics if enabled on annotation if (metrics.captureColdStart()) { diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java new file mode 100644 index 000000000..2d0250d7a --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java @@ -0,0 +1,101 @@ +package software.amazon.lambda.powertools.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junitpioneer.jupiter.SetEnvironmentVariable; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.metrics.model.MetricUnit; + +@ExtendWith(MockitoExtension.class) +class RequestHandlerTest { + + // For developer convenience, no exceptions should be thrown when using a plain Lambda Context mock + @Mock + Context lambdaContext; + + private final PrintStream standardOut = System.out; + private ByteArrayOutputStream outputStreamCaptor; + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + outputStreamCaptor = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + void tearDown() throws Exception { + System.setOut(standardOut); + + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); + + field = MetricsFactory.class.getDeclaredField("provider"); + field.setAccessible(true); + field.set(null, new software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider()); + } + + @Test + void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, lambdaContext); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("test-metric")).isTrue(); + assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("CustomNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); + } + + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") + @Test + void shouldNotCaptureMetricsWhenDisabled() { + // Given + RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, lambdaContext); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + assertThat(emfOutput).isEmpty(); + } + + static class HandlerWithMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics(namespace = "CustomNamespace", service = "CustomService") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } +} From a42ae1340e8696706a759560443f46a43762c8cd Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 12:23:19 +0200 Subject: [PATCH 4/9] Reset outputstream in unit test docs. --- docs/core/metrics.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 980fc8680..72e6323cc 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -589,16 +589,17 @@ class MetricsTestExample { Context lambdaContext; private final PrintStream standardOut = System.out; - private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private ByteArrayOutputStream outputStreamCaptor; private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach void setUp() { + outputStreamCaptor = new ByteArrayOutputStream(); System.setOut(new PrintStream(outputStreamCaptor)); } @AfterEach - void tearDown() { + void tearDown() throws Exception { System.setOut(standardOut); } From 015c763253b5d3aa4d2141d7d8a277c91b45c6f6 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 12:34:04 +0200 Subject: [PATCH 5/9] Make stdout stream field static and final. --- .../amazon/lambda/powertools/metrics/RequestHandlerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java index 2d0250d7a..49fff97bd 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java @@ -29,7 +29,7 @@ class RequestHandlerTest { @Mock Context lambdaContext; - private final PrintStream standardOut = System.out; + private static final PrintStream STDOUT = System.out; private ByteArrayOutputStream outputStreamCaptor; private final ObjectMapper objectMapper = new ObjectMapper(); @@ -41,7 +41,7 @@ void setUp() { @AfterEach void tearDown() throws Exception { - System.setOut(standardOut); + System.setOut(STDOUT); // Reset the singleton state between tests java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); From f74103562d60f7bb3586facfbbf1cdff7a46710d Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 13:40:40 +0200 Subject: [PATCH 6/9] Fix issue when function name is not set. --- docs/core/metrics.md | 44 ++++++++++++++---- .../metrics/internal/LambdaMetricsAspect.java | 5 ++- .../metrics/RequestHandlerTest.java | 45 ++++++++++++++----- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 72e6323cc..2b7f48f17 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -558,6 +558,21 @@ If you would like to suppress metrics output during your unit tests, you can use When unit testing your code, you can run assertions against the output generated by the `Metrics` Singleton. For the `EmfMetricsLogger`, you can assert the generated JSON blob following the [CloudWatch EMF specification](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html) against your expected output. +Make sure to set a test metrics namespace and service name to run assertions against metrics. For example, by setting the following environment variables in your tests: + +```xml + + org.apache.maven.plugins + maven-surefire-plugin + + + TestService + TestNamespace + + + +``` + Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. ```java hl_lines="34 39 55-60" @@ -614,19 +629,30 @@ class MetricsTestExample { // Then String emfOutput = outputStreamCaptor.toString().trim(); - JsonNode rootNode = objectMapper.readTree(emfOutput); - - assertThat(rootNode.has("test-metric")).isTrue(); - assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100.0); - assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) - .isEqualTo("CustomNamespace"); - assertThat(rootNode.has("Service")).isTrue(); - assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); + String[] jsonLines = emfOutput.split("\n"); + + // First JSON object should be the cold start metric + JsonNode coldStartNode = objectMapper.readTree(jsonLines[0]); + assertThat(coldStartNode.has("ColdStart")).isTrue(); + assertThat(coldStartNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(coldStartNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(coldStartNode.has("Service")).isTrue(); + assertThat(coldStartNode.get("Service").asText()).isEqualTo("TestService"); + + // Second JSON object should be the regular metric + JsonNode regularNode = objectMapper.readTree(jsonLines[1]); + assertThat(regularNode.has("test-metric")).isTrue(); + assertThat(regularNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(regularNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(regularNode.has("Service")).isTrue(); + assertThat(regularNode.get("Service").asText()).isEqualTo("TestService"); } static class HandlerWithMetricsAnnotation implements RequestHandler, String> { @Override - @FlushMetrics(namespace = "CustomNamespace", service = "CustomService") + @FlushMetrics(captureColdStart = true) public String handleRequest(Map input, Context context) { Metrics metrics = MetricsFactory.getMetricsInstance(); metrics.addMetric("test-metric", 100, MetricUnit.COUNT); diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java index a05ce9568..32824e24f 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java @@ -136,8 +136,9 @@ private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetr } // Add function name - coldStartDimensions.addDimension("FunctionName", - funcName != null ? funcName : extractedContext.getFunctionName()); + if (funcName != null) { + coldStartDimensions.addDimension("FunctionName", funcName); + } metricsInstance.captureColdStartMetric(extractedContext, coldStartDimensions); } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java index 49fff97bd..d94a6bbe8 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java @@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @@ -20,6 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.model.MetricUnit; @ExtendWith(MockitoExtension.class) @@ -34,9 +36,19 @@ class RequestHandlerTest { private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach - void setUp() { + void setUp() throws Exception { outputStreamCaptor = new ByteArrayOutputStream(); System.setOut(new PrintStream(outputStreamCaptor)); + + // Reset LambdaHandlerProcessor's SERVICE_NAME + Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); + resetServiceName.setAccessible(true); + resetServiceName.invoke(null); + + // Reset IS_COLD_START + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + coldStartField.setAccessible(true); + coldStartField.set(null, null); } @AfterEach @@ -54,6 +66,8 @@ void tearDown() throws Exception { } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "TestNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "TestService") void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { // Given RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); @@ -64,14 +78,25 @@ void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { // Then String emfOutput = outputStreamCaptor.toString().trim(); - JsonNode rootNode = objectMapper.readTree(emfOutput); - - assertThat(rootNode.has("test-metric")).isTrue(); - assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100.0); - assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) - .isEqualTo("CustomNamespace"); - assertThat(rootNode.has("Service")).isTrue(); - assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); + String[] jsonLines = emfOutput.split("\n"); + + // First JSON object should be the cold start metric + JsonNode coldStartNode = objectMapper.readTree(jsonLines[0]); + assertThat(coldStartNode.has("ColdStart")).isTrue(); + assertThat(coldStartNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(coldStartNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(coldStartNode.has("Service")).isTrue(); + assertThat(coldStartNode.get("Service").asText()).isEqualTo("TestService"); + + // Second JSON object should be the regular metric + JsonNode regularNode = objectMapper.readTree(jsonLines[1]); + assertThat(regularNode.has("test-metric")).isTrue(); + assertThat(regularNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(regularNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(regularNode.has("Service")).isTrue(); + assertThat(regularNode.get("Service").asText()).isEqualTo("TestService"); } @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") @@ -91,7 +116,7 @@ void shouldNotCaptureMetricsWhenDisabled() { static class HandlerWithMetricsAnnotation implements RequestHandler, String> { @Override - @FlushMetrics(namespace = "CustomNamespace", service = "CustomService") + @FlushMetrics(captureColdStart = true) public String handleRequest(Map input, Context context) { Metrics metrics = MetricsFactory.getMetricsInstance(); metrics.addMetric("test-metric", 100, MetricUnit.COUNT); From a20a3abaf3568155ecbcd32677634ec976027ddf Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 13:44:33 +0200 Subject: [PATCH 7/9] Fix hl_lines in docs. --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 2b7f48f17..f285a23c7 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -575,7 +575,7 @@ Make sure to set a test metrics namespace and service name to run assertions aga Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. -```java hl_lines="34 39 55-60" +```java hl_lines="34 40 56-61" import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayOutputStream; From 8fac196be51478b17bf00adb4ed3a6157560ed91 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 13:44:44 +0200 Subject: [PATCH 8/9] Fix hl_lines in docs. --- docs/core/metrics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index f285a23c7..490cb55c6 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -575,7 +575,7 @@ Make sure to set a test metrics namespace and service name to run assertions aga Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. -```java hl_lines="34 40 56-61" +```java hl_lines="35 40 56-72" import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayOutputStream; From 4eb256a4fe699eda54a346462b1801c6ea8a9cae Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 3 Sep 2025 14:36:34 +0200 Subject: [PATCH 9/9] Remove java8 from sam templates. --- docs/core/metrics.md | 2 +- docs/core/tracing.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 490cb55c6..61d4c38f0 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -140,7 +140,7 @@ For most use-cases, we recommend using Environment variables and only overwrite Type: AWS::Serverless::Function Properties: ... - Runtime: java8 + Runtime: java11 Environment: Variables: POWERTOOLS_SERVICE_NAME: payment diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 883f8db86..8129d45ba 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -105,7 +105,7 @@ Before your use this utility, your AWS Lambda function [must have permissions](h Type: AWS::Serverless::Function Properties: ... - Runtime: java8 + Runtime: java11 Tracing: Active Environment: @@ -191,7 +191,7 @@ different supported `captureMode` to record response, exception or both. Type: AWS::Serverless::Function Properties: ... - Runtime: java8 + Runtime: java11 Tracing: Active Environment: