Skip to content

Commit 1bd0222

Browse files
committed
additional cw-metrics
1 parent 682214d commit 1bd0222

File tree

6 files changed

+62
-5
lines changed

6 files changed

+62
-5
lines changed

src/main/java/software/amazon/cloudformation/LambdaWrapper.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ public void handleRequest(final InputStream inputStream, final OutputStream outp
312312

313313
if (handlerResponse.getStatus() == OperationStatus.IN_PROGRESS && !isMutatingAction) {
314314
throw new TerminalException("READ and LIST handlers must return synchronously.");
315+
} else if (handlerResponse.getStatus() != OperationStatus.FAILED) {
316+
this.metricsPublisherProxy.publishExceptionCountMetric(Instant.now(), request.getAction(), false);
315317
}
316318

317319
return handlerResponse;
@@ -346,6 +348,11 @@ public void handleRequest(final InputStream inputStream, final OutputStream outp
346348
throw new TerminalException("Handler failed to provide a response.");
347349
}
348350

351+
if (handlerResponse.getStatus() == OperationStatus.FAILED) {
352+
publishExceptionMetric(request.getAction(), new Throwable(handlerResponse.getMessage()),
353+
handlerResponse.getErrorCode());
354+
}
355+
349356
return handlerResponse;
350357
} catch (final BaseHandlerException e) {
351358
publishExceptionMetric(request.getAction(), e, e.getErrorCode());
@@ -464,6 +471,9 @@ public abstract ProgressEvent<ResourceT, CallbackT> invokeHandler(AmazonWebServi
464471
private void publishExceptionMetric(final Action action, final Throwable ex, final HandlerErrorCode handlerErrorCode) {
465472
if (this.metricsPublisherProxy != null) {
466473
this.metricsPublisherProxy.publishExceptionMetric(Instant.now(), action, ex, handlerErrorCode);
474+
this.metricsPublisherProxy.publishExceptionByErrorCodeMetric(Instant.now(), action, handlerErrorCode);
475+
// always puts failed events
476+
this.metricsPublisherProxy.publishExceptionCountMetric(Instant.now(), action, true);
467477
} else {
468478
// Lambda logger is the only fallback if metrics publisher proxy is not
469479
// initialized.

src/main/java/software/amazon/cloudformation/metrics/Metric.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public class Metric {
1818

1919
public static final String METRIC_NAMESPACE_ROOT = "AWS/CloudFormation";
2020
public static final String METRIC_NAME_HANDLER_EXCEPTION = "HandlerException";
21+
public static final String METRIC_NAME_HANDLER_EXCEPTION_BY_ERROR_CODE = "HandlerExceptionByErrorCode";
22+
public static final String METRIC_NAME_HANDLER_EXCEPTION_BY_EXCEPTION_COUNT = "HandlerExceptionByExceptionCount";
2123
public static final String METRIC_NAME_HANDLER_DURATION = "HandlerInvocationDuration";
2224
public static final String METRIC_NAME_HANDLER_INVOCATION_COUNT = "HandlerInvocationCount";
2325

src/main/java/software/amazon/cloudformation/metrics/MetricsPublisher.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ public void publishExceptionMetric(final Instant timestamp,
4242
final HandlerErrorCode handlerErrorCode) {
4343
}
4444

45+
public void
46+
publishExceptionByErrorCodeMetric(final Instant timestamp, final Action action, final HandlerErrorCode handlerErrorCode) {
47+
}
48+
49+
public void publishExceptionCountMetric(final Instant timestamp, final Action action, final boolean thrown) {
50+
}
51+
4552
public void publishInvocationMetric(final Instant timestamp, final Action action) {
4653
}
4754

src/main/java/software/amazon/cloudformation/metrics/MetricsPublisherImpl.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,24 @@ public void publishExceptionMetric(final Instant timestamp,
6666
publishMetric(Metric.METRIC_NAME_HANDLER_EXCEPTION, dimensions, StandardUnit.COUNT, 1.0, timestamp);
6767
}
6868

69+
@Override
70+
public void
71+
publishExceptionByErrorCodeMetric(final Instant timestamp, final Action action, final HandlerErrorCode handlerErrorCode) {
72+
Map<String, String> dimensions = new HashMap<>();
73+
dimensions.put(Metric.DIMENSION_KEY_ACTION_TYPE, action == null ? "NO_ACTION" : action.name());
74+
dimensions.put(Metric.DIMENSION_KEY_HANDLER_ERROR_CODE, handlerErrorCode.name());
75+
76+
publishMetric(Metric.METRIC_NAME_HANDLER_EXCEPTION_BY_ERROR_CODE, dimensions, StandardUnit.COUNT, 1.0, timestamp);
77+
}
78+
79+
public void publishExceptionCountMetric(final Instant timestamp, final Action action, final boolean thrown) {
80+
Map<String, String> dimensions = new HashMap<>();
81+
dimensions.put(Metric.DIMENSION_KEY_ACTION_TYPE, action == null ? "NO_ACTION" : action.name());
82+
83+
publishMetric(Metric.METRIC_NAME_HANDLER_EXCEPTION_BY_EXCEPTION_COUNT, dimensions, StandardUnit.COUNT, thrown ? 1.0 : 0.0,
84+
timestamp);
85+
}
86+
6987
@Override
7088
public void publishProviderLogDeliveryExceptionMetric(final Instant timestamp, final Throwable e) {
7189
Map<String, String> dimensions = new HashMap<>();

src/main/java/software/amazon/cloudformation/proxy/MetricsPublisherProxy.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ public void publishExceptionMetric(final Instant timestamp,
3535
.forEach(metricsPublisher -> metricsPublisher.publishExceptionMetric(timestamp, action, e, handlerErrorCode));
3636
}
3737

38+
public void
39+
publishExceptionByErrorCodeMetric(final Instant timestamp, final Action action, final HandlerErrorCode handlerErrorCode) {
40+
metricsPublishers.stream()
41+
.forEach(metricsPublisher -> metricsPublisher.publishExceptionByErrorCodeMetric(timestamp, action, handlerErrorCode));
42+
}
43+
44+
public void publishExceptionCountMetric(final Instant timestamp, final Action action, final boolean thrown) {
45+
metricsPublishers.stream()
46+
.forEach(metricsPublisher -> metricsPublisher.publishExceptionCountMetric(timestamp, action, thrown));
47+
}
48+
3849
public void publishInvocationMetric(final Instant timestamp, final Action action) {
3950
metricsPublishers.stream().forEach(metricsPublisher -> metricsPublisher.publishInvocationMetric(timestamp, action));
4051
}

src/test/java/software/amazon/cloudformation/LambdaWrapperTest.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,11 @@ public void invokeHandler_nullResponse_returnsFailure(final String requestDataPa
158158
verifyInitialiseRuntime();
159159

160160
// validation failure metric should be published for final error handling
161-
verify(providerMetricsPublisher, times(1)).publishExceptionMetric(any(Instant.class), any(),
162-
any(TerminalException.class), any(HandlerErrorCode.class));
161+
verify(providerMetricsPublisher).publishExceptionMetric(any(Instant.class), any(), any(TerminalException.class),
162+
any(HandlerErrorCode.class));
163+
verify(providerMetricsPublisher).publishExceptionByErrorCodeMetric(any(Instant.class), any(),
164+
any(HandlerErrorCode.class));
165+
verify(providerMetricsPublisher).publishExceptionCountMetric(any(Instant.class), any(), any(Boolean.class));
163166

164167
// all metrics should be published even on terminal failure
165168
verify(providerMetricsPublisher, times(1)).publishInvocationMetric(any(Instant.class), eq(action));
@@ -399,14 +402,19 @@ public void invokeHandler_InProgress_returnsInProgress(final String requestDataP
399402
// verify output response
400403
verifyHandlerResponse(out, ProgressEvent.<TestModel, TestContext>builder().status(OperationStatus.IN_PROGRESS)
401404
.resourceModel(TestModel.builder().property1("abc").property2(123).build()).build());
405+
verify(providerMetricsPublisher).publishExceptionCountMetric(any(Instant.class), eq(action), eq(Boolean.FALSE));
402406
} else {
403407
verifyHandlerResponse(out,
404408
ProgressEvent.<TestModel, TestContext>builder().status(OperationStatus.FAILED)
405409
.errorCode(HandlerErrorCode.InternalFailure).message("READ and LIST handlers must return synchronously.")
406410
.build());
407-
verify(providerMetricsPublisher, times(1)).publishExceptionMetric(any(Instant.class), eq(action),
411+
verify(providerMetricsPublisher).publishExceptionMetric(any(Instant.class), eq(action),
408412
any(TerminalException.class), eq(HandlerErrorCode.InternalFailure));
413+
verify(providerMetricsPublisher).publishExceptionByErrorCodeMetric(any(Instant.class), eq(action),
414+
eq(HandlerErrorCode.InternalFailure));
415+
verify(providerMetricsPublisher).publishExceptionCountMetric(any(Instant.class), eq(action), eq(Boolean.TRUE));
409416
}
417+
410418
// validation failure metric should not be published
411419
verifyNoMoreInteractions(providerMetricsPublisher);
412420

@@ -446,8 +454,9 @@ public void reInvokeHandler_InProgress_returnsInProgress(final String requestDat
446454
verifyInitialiseRuntime();
447455

448456
// all metrics should be published, once for a single invocation
449-
verify(providerMetricsPublisher, times(1)).publishInvocationMetric(any(Instant.class), eq(action));
450-
verify(providerMetricsPublisher, times(1)).publishDurationMetric(any(Instant.class), eq(action), anyLong());
457+
verify(providerMetricsPublisher).publishInvocationMetric(any(Instant.class), eq(action));
458+
verify(providerMetricsPublisher).publishDurationMetric(any(Instant.class), eq(action), anyLong());
459+
verify(providerMetricsPublisher).publishExceptionCountMetric(any(Instant.class), eq(action), eq(Boolean.FALSE));
451460

452461
// validation failure metric should not be published
453462
verifyNoMoreInteractions(providerMetricsPublisher);

0 commit comments

Comments
 (0)