diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 28a35dce0..1cd9446be 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -27,4 +27,6 @@ jobs: echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - name: Build docs website - run: make build-docs-website \ No newline at end of file + run: | + echo "GIT_PYTHON_REFRESH=quiet" + make build-docs-website \ No newline at end of file diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 0839be050..4d250df48 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -186,7 +186,7 @@ This will be available in CloudWatch Logs to ease operations on high cardinal da By default, all metrics emitted via module captures `Service` as one of the default dimension. This is either specified via `POWERTOOLS_SERVICE_NAME` environment variable or via `service` attribute on `Metrics` annotation. If you wish to override the default -Dimension, it can be done via `#!java MetricsUtils.defaultDimensionSet()`. +Dimension, it can be done via `#!java MetricsUtils.defaultDimensions()`. === "App.java" @@ -199,7 +199,7 @@ Dimension, it can be done via `#!java MetricsUtils.defaultDimensionSet()`. MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); static { - MetricsUtils.defaultDimensionSet(DimensionSet.of("CustomDimension", "booking")); + MetricsUtils.defaultDimensions(DimensionSet.of("CustomDimension", "booking")); } @Override diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java index 8c7ff2a5c..f7465e663 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java @@ -25,7 +25,7 @@ */ public final class MetricsUtils { private static final MetricsLogger metricsLogger = new MetricsLogger(); - private static DimensionSet defaultDimensionSet; + private static DimensionSet[] defaultDimensions; private MetricsUtils() { } @@ -39,14 +39,29 @@ public static MetricsLogger metricsLogger() { return metricsLogger; } + /** + * Configure default dimension to be used by logger. + * By default, @{@link Metrics} annotation captures configured service as a dimension Service + * @param dimensionSets Default value of dimensions set for logger + */ + public static void defaultDimensions(final DimensionSet... dimensionSets) { + MetricsUtils.defaultDimensions = dimensionSets; + } + /** * Configure default dimension to be used by logger. * By default, @{@link Metrics} annotation captures configured service as a dimension Service * @param dimensionSet Default value of dimension set for logger + * @deprecated use {@link #defaultDimensions(DimensionSet...)} instead + * */ + @Deprecated public static void defaultDimensionSet(final DimensionSet dimensionSet) { requireNonNull(dimensionSet, "Null dimension set not allowed"); - MetricsUtils.defaultDimensionSet = dimensionSet; + + if(dimensionSet.getDimensionKeys().size() > 0) { + defaultDimensions(dimensionSet); + } } @@ -105,12 +120,12 @@ public static void withSingleMetric(final String name, } } - public static DimensionSet defaultDimensionSet() { - return defaultDimensionSet; + public static DimensionSet[] getDefaultDimensions() { + return defaultDimensions; } public static boolean hasDefaultDimension() { - return null != defaultDimensionSet && defaultDimensionSet.getDimensionKeys().size() > 0; + return null != defaultDimensions; } private static void captureRequestAndTraceId(MetricsLogger metricsLogger) { @@ -137,7 +152,7 @@ private static MetricsLogger logger() { MetricsContext metricsContext = new MetricsContext(); if (hasDefaultDimension()) { - metricsContext.setDefaultDimensions(defaultDimensionSet()); + metricsContext.setDimensions(defaultDimensions); } return new MetricsLogger(new EnvironmentProvider(), metricsContext); 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 2adff4b8a..f429c52e7 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 @@ -12,6 +12,7 @@ import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsUtils; import software.amazon.lambda.powertools.metrics.ValidationException; import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.dimensionsCount; @@ -23,7 +24,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.metrics.MetricsUtils.defaultDimensionSet; import static software.amazon.lambda.powertools.metrics.MetricsUtils.hasDefaultDimension; import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; @@ -125,10 +125,10 @@ public static void refreshMetricsContext(Metrics metrics) { f.setAccessible(true); MetricsContext context = new MetricsContext(); - DimensionSet defaultDimensionSet = hasDefaultDimension() ? defaultDimensionSet() - : DimensionSet.of("Service", service(metrics)); + DimensionSet[] defaultDimensions = hasDefaultDimension() ? MetricsUtils.getDefaultDimensions() + : new DimensionSet[]{DimensionSet.of("Service", service(metrics))}; - context.setDefaultDimensions(defaultDimensionSet); + context.setDimensions(defaultDimensions); f.set(metricsLogger(), context); } catch (NoSuchFieldException | IllegalAccessException e) { diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 2ff2cce8e..449f12815 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -52,7 +52,7 @@ void singleMetricsCaptureUtilityWithDefaultDimension() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); - MetricsUtils.defaultDimensionSet(DimensionSet.of("Service", "Booking")); + MetricsUtils.defaultDimensions(DimensionSet.of("Service", "Booking")); MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", metricsLogger -> {}); diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java index 308601e83..f66269546 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java @@ -7,14 +7,14 @@ import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.metrics.Metrics; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.defaultDimensionSet; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.defaultDimensions; import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; public class PowertoolsMetricsEnabledDefaultDimensionHandler implements RequestHandler { static { - defaultDimensionSet(DimensionSet.of("CustomDimension", "booking")); + defaultDimensions(DimensionSet.of("CustomDimension", "booking")); } @Override diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java new file mode 100644 index 000000000..761362f43 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java @@ -0,0 +1,29 @@ +package software.amazon.lambda.powertools.metrics.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsUtils; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; + +public class PowertoolsMetricsEnabledDefaultNoDimensionHandler implements RequestHandler { + + static { + MetricsUtils.defaultDimensions(); + } + + @Override + @Metrics(namespace = "ExampleApplication", service = "booking") + public Object handleRequest(Object input, Context context) { + MetricsLogger metricsLogger = metricsLogger(); + metricsLogger.putMetric("Metric1", 1, Unit.BYTES); + + withSingleMetric("Metric2", 1, Unit.COUNT, log -> {}); + + return null; + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index 438558f71..6c18d5d7a 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -24,6 +24,7 @@ import software.amazon.lambda.powertools.metrics.ValidationException; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsColdStartEnabledHandler; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultDimensionHandler; +import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultNoDimensionHandler; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledHandler; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledStreamHandler; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsExceptionWhenNoMetricsHandler; @@ -49,7 +50,6 @@ public class LambdaMetricsAspectTest { private final PrintStream originalOut = System.out; private final ObjectMapper mapper = new ObjectMapper(); private RequestHandler requestHandler; - private RequestStreamHandler streamHandler; @BeforeAll @@ -80,7 +80,7 @@ public void metricsWithoutColdStart() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsEnabledHandler(); requestHandler.handleRequest("input", context); @@ -154,6 +154,45 @@ public void metricsWithDefaultDimensionSpecified() { } } + @Test + public void metricsWithDefaultNoDimensionSpecified() { + try (MockedStatic mocked = mockStatic(SystemWrapper.class); + MockedStatic internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + + mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); + internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + + requestHandler = new PowertoolsMetricsEnabledDefaultNoDimensionHandler(); + + requestHandler.handleRequest("input", context); + + assertThat(out.toString().split("\n")) + .hasSize(2) + .satisfies(s -> { + Map logAsJson = readAsJson(s[0]); + + assertThat(logAsJson) + .containsEntry("Metric2", 1.0) + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") + .containsEntry("function_request_id", "123ABC"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=ExampleApplication"); + + logAsJson = readAsJson(s[1]); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); + } + } + @Test public void metricsWithColdStart() { @@ -161,7 +200,7 @@ public void metricsWithColdStart() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); requestHandler.handleRequest("input", context); @@ -196,7 +235,7 @@ public void noColdStartMetricsWhenColdStartDone() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); requestHandler.handleRequest("input", context); @@ -241,8 +280,8 @@ public void metricsWithStreamHandler() throws IOException { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); - streamHandler = new PowertoolsMetricsEnabledStreamHandler(); + MetricsUtils.defaultDimensions(null); + RequestStreamHandler streamHandler = new PowertoolsMetricsEnabledStreamHandler(); streamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); @@ -264,7 +303,7 @@ public void exceptionWhenNoMetricsEmitted() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsExceptionWhenNoMetricsHandler(); assertThatExceptionOfType(ValidationException.class) @@ -279,7 +318,7 @@ public void noExceptionWhenNoMetricsEmitted() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsNoExceptionWhenNoMetricsHandler(); requestHandler.handleRequest("input", context); @@ -299,7 +338,7 @@ public void noExceptionWhenNoMetricsEmitted() { public void allowWhenNoDimensionsSet() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsNoDimensionsHandler(); requestHandler.handleRequest("input", context); @@ -321,7 +360,7 @@ public void exceptionWhenTooManyDimensionsSet() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsTooManyDimensionsHandler(); @@ -336,7 +375,7 @@ public void metricsPublishedEvenHandlerThrowsException() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensionSet(new DimensionSet()); + MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsWithExceptionInHandler(); assertThatExceptionOfType(IllegalStateException.class)