Skip to content

Commit 4fca00a

Browse files
committed
feat(metrics): introduce MetricUtils.withMetric utility
closes aws-powertools#999
1 parent 4fb0384 commit 4fca00a

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

docs/core/metrics.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,28 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `withSingle
233233
});
234234
}
235235
}
236+
```
237+
238+
## Creating metrics with different configurations
239+
240+
Use `withMetric` if you have one or more metrics that should have different configurations e.g. dimensions or namespace.
241+
242+
=== "App.java"
243+
244+
```java hl_lines="7 8 9 10 11 12 13"
245+
import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric;
246+
247+
public class App implements RequestHandler<Object, Object> {
248+
249+
@Override
250+
public Object handleRequest(Object input, Context context) {
251+
withMetric(metric -> {
252+
// override default dimensions
253+
metric.setDimensions(DimensionSet.of("AnotherService", "CustomService"));
254+
// add metrics
255+
metric.putMetric("CustomMetrics1", 1, Unit.COUNT);
256+
metric.putMetric("CustomMetrics2", 5, Unit.COUNT);
257+
});
258+
}
259+
}
236260
```

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,26 @@ public static void withSingleMetric(final String name,
121121
}
122122
}
123123

124+
/**
125+
* Provide and immediately flush a {@link MetricsLogger}. It will use the default namespace
126+
* specified either on {@link Metrics} annotation or via POWERTOOLS_METRICS_NAMESPACE env var.
127+
* It by default captures function_request_id as property if used together with {@link Metrics} annotation. It will also
128+
* capture xray_trace_id as property if tracing is enabled.
129+
*
130+
* @param logger the MetricsLogger
131+
*/
132+
public static void withMetric(final Consumer<MetricsLogger> logger) {
133+
MetricsLogger metricsLogger = logger();
134+
135+
try {
136+
metricsLogger.setNamespace(defaultNameSpace());
137+
captureRequestAndTraceId(metricsLogger);
138+
logger.accept(metricsLogger);
139+
} finally {
140+
metricsLogger.flush();
141+
}
142+
}
143+
124144
public static DimensionSet[] getDefaultDimensions() {
125145
return Arrays.copyOf(defaultDimensions, defaultDimensions.length);
126146
}

powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,38 @@ void singleMetricsCaptureUtilityWithDefaultNameSpace() {
123123
}
124124
}
125125

126+
@Test
127+
void metricsCaptureUtilityWithDefaultNameSpace() {
128+
try (MockedStatic<SystemWrapper> mocked = mockStatic(SystemWrapper.class);
129+
MockedStatic<software.amazon.lambda.powertools.core.internal.SystemWrapper> internalWrapper = mockStatic(software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) {
130+
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
131+
mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName");
132+
internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")).thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"");
133+
134+
MetricsUtils.withMetric(metricsLogger -> {
135+
metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"));
136+
metricsLogger.putMetric("Metric1", 1, Unit.COUNT);
137+
});
138+
139+
assertThat(out.toString())
140+
.satisfies(s -> {
141+
Map<String, Object> logAsJson = readAsJson(s);
142+
143+
assertThat(logAsJson)
144+
.containsEntry("Metric1", 1.0)
145+
.containsEntry("Dimension1", "Value1")
146+
.containsKey("_aws")
147+
.containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793");
148+
149+
Map<String, Object> aws = (Map<String, Object>) logAsJson.get("_aws");
150+
151+
assertThat(aws.get("CloudWatchMetrics"))
152+
.asString()
153+
.contains("Namespace=GlobalName");
154+
});
155+
}
156+
}
157+
126158
@Test
127159
void shouldThrowExceptionWhenDefaultDimensionIsNull() {
128160
assertThatNullPointerException()

0 commit comments

Comments
 (0)