Skip to content

Commit 85a4da5

Browse files
feat: capture metrics even when handler results in exception (#286)
1 parent d2dbf10 commit 85a4da5

File tree

4 files changed

+58
-8
lines changed

4 files changed

+58
-8
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ on:
1111
- 'powertools-tracing/**'
1212
- 'powertools-validation/**'
1313
- 'powertools-parameters/**'
14+
- 'powertools-metrics/**'
1415
- 'pom.xml'
1516
- '.github/workflows/**'
1617
push:
@@ -21,8 +22,11 @@ on:
2122
- 'powertools-logging/**'
2223
- 'powertools-sqs/**'
2324
- 'powertools-tracing/**'
25+
- 'powertools-validation/**'
26+
- 'powertools-parameters/**'
27+
- 'powertools-metrics/**'
2428
- 'pom.xml'
25-
29+
- '.github/workflows/**'
2630
jobs:
2731
build:
2832
runs-on: ubuntu-latest

powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,12 @@ public Object around(ProceedingJoinPoint pjp,
5353
coldStartSingleMetricIfApplicable(pjp, metrics);
5454

5555
try {
56-
Object proceed = pjp.proceed(proceedArgs);
56+
return pjp.proceed(proceedArgs);
5757

58+
} finally {
5859
coldStartDone();
59-
60-
validateBeforeFlushingMetrics(metrics);
61-
60+
validateMetricsAndRefreshOnFailure(metrics);
6261
logger.flush();
63-
return proceed;
64-
65-
} finally {
6662
refreshMetricsContext();
6763
}
6864
}
@@ -105,6 +101,16 @@ private String service(Metrics metrics) {
105101
return !"".equals(metrics.service()) ? metrics.service() : serviceName();
106102
}
107103

104+
private void validateMetricsAndRefreshOnFailure(Metrics metrics) {
105+
try {
106+
107+
validateBeforeFlushingMetrics(metrics);
108+
} catch (ValidationException e){
109+
refreshMetricsContext();
110+
throw e;
111+
}
112+
}
113+
108114
// This can be simplified after this issues https://github.com/awslabs/aws-embedded-metrics-java/issues/35 is fixed
109115
private static void refreshMetricsContext() {
110116
try {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package software.amazon.lambda.powertools.metrics.handlers;
2+
3+
import com.amazonaws.services.lambda.runtime.Context;
4+
import com.amazonaws.services.lambda.runtime.RequestHandler;
5+
import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger;
6+
import software.amazon.lambda.powertools.metrics.Metrics;
7+
8+
import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger;
9+
10+
public class PowertoolsMetricsWithExceptionInHandler implements RequestHandler<Object, Object> {
11+
12+
@Override
13+
@Metrics(namespace = "ExampleApplication", service = "booking")
14+
public Object handleRequest(Object input, Context context) {
15+
MetricsLogger metricsLogger = metricsLogger();
16+
metricsLogger.putMetric("CoolMetric", 1);
17+
throw new IllegalStateException("Whoops, unexpected exception");
18+
}
19+
}

powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoDimensionsHandler;
2828
import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoExceptionWhenNoMetricsHandler;
2929
import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsTooManyDimensionsHandler;
30+
import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsWithExceptionInHandler;
3031

3132
import static java.util.Collections.emptyMap;
3233
import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField;
@@ -233,6 +234,26 @@ public void exceptionWhenTooManyDimensionsSet() {
233234
}
234235
}
235236

237+
@Test
238+
public void metricsPublishedEvenHandlerThrowsException() {
239+
requestHandler = new PowertoolsMetricsWithExceptionInHandler();
240+
try (MockedStatic<SystemWrapper> mocked = mockStatic(SystemWrapper.class)) {
241+
mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda");
242+
assertThatExceptionOfType(IllegalStateException.class)
243+
.isThrownBy(() -> requestHandler.handleRequest("input", context))
244+
.withMessage("Whoops, unexpected exception");
245+
246+
assertThat(out.toString())
247+
.satisfies(s -> {
248+
Map<String, Object> logAsJson = readAsJson(s);
249+
assertThat(logAsJson)
250+
.containsEntry("CoolMetric", 1.0)
251+
.containsEntry("Service", "booking")
252+
.containsKey("_aws");
253+
});
254+
}
255+
}
256+
236257
private void setupContext() {
237258
when(context.getFunctionName()).thenReturn("testFunction");
238259
when(context.getInvokedFunctionArn()).thenReturn("testArn");

0 commit comments

Comments
 (0)