Skip to content

Commit 65e52db

Browse files
authored
Merge pull request #817 from commercetools/telemetry-error-capture
[DEVX-468] Capture errors in telemetry middleware
2 parents ccf877f + 79578ef commit 65e52db

File tree

5 files changed

+90
-19
lines changed

5 files changed

+90
-19
lines changed

commercetools/commercetools-monitoring-datadog/src/main/java/com/commercetools/monitoring/datadog/DatadogMiddleware.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.datadog.api.client.ApiException;
1313
import com.datadog.api.client.v2.api.MetricsApi;
1414

15+
import io.vrap.rmf.base.client.ApiHttpException;
1516
import io.vrap.rmf.base.client.ApiHttpRequest;
1617
import io.vrap.rmf.base.client.ApiHttpResponse;
1718
import io.vrap.rmf.base.client.http.TelemetryMiddleware;
@@ -51,14 +52,23 @@ public DatadogMiddleware(final MetricsApi apiInstance) {
5152
public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
5253
Function<ApiHttpRequest, CompletableFuture<ApiHttpResponse<byte[]>>> next) {
5354
final Instant start = Instant.now();
54-
return next.apply(request).thenApply(response -> {
55+
return next.apply(request).handle((response, throwable) -> {
56+
final int statusCode;
57+
if (response != null) {
58+
statusCode = response.getStatusCode();
59+
}
60+
else if (throwable instanceof ApiHttpException && ((ApiHttpException) throwable).getResponse() != null) {
61+
statusCode = ((ApiHttpException) throwable).getResponse().getStatusCode();
62+
}
63+
else {
64+
statusCode = 0;
65+
}
5566
try {
5667
submitClientDurationMetric(request, apiInstance, Duration.between(start, Instant.now()).toMillis(),
57-
response);
58-
submitTotalRequestsMetric(request, apiInstance, response);
59-
60-
if (response.getStatusCode() >= 400) {
61-
submitErrorRequestsMetric(request, apiInstance, response);
68+
statusCode);
69+
submitTotalRequestsMetric(request, apiInstance, statusCode);
70+
if (statusCode >= 400 || throwable != null) {
71+
submitErrorRequestsMetric(request, apiInstance, statusCode);
6272
}
6373
}
6474
catch (ApiException e) {

commercetools/commercetools-monitoring-datadog/src/main/java/com/commercetools/monitoring/datadog/DatadogUtils.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,50 @@ public class DatadogUtils {
2828

2929
protected static void submitClientDurationMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
3030
final double durationInMillis, final ApiHttpResponse<byte[]> response) throws ApiException {
31+
submitClientDurationMetric(request, apiInstance, durationInMillis, response.getStatusCode());
32+
}
33+
34+
protected static void submitClientDurationMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
35+
final double durationInMillis, final int statusCode) throws ApiException {
3136
final String name = PREFIX + "." + CLIENT_DURATION;
3237
final MetricIntakeType type = MetricIntakeType.UNSPECIFIED;
33-
submitMetricWithHttpTags(name, durationInMillis, type, "ms", request, apiInstance, response);
38+
submitMetricWithHttpTags(name, durationInMillis, type, "ms", request, apiInstance, statusCode);
3439
}
3540

3641
protected static void submitErrorRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
3742
final ApiHttpResponse<byte[]> response) throws ApiException {
43+
submitErrorRequestsMetric(request, apiInstance, response.getStatusCode());
44+
}
45+
46+
protected static void submitErrorRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
47+
final int statusCode) throws ApiException {
3848
final String name = PREFIX + "." + CLIENT_REQUEST_ERROR;
3949
final MetricIntakeType count = MetricIntakeType.COUNT;
40-
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, response);
50+
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, statusCode);
4151
}
4252

4353
protected static void submitTotalRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
4454
final ApiHttpResponse<byte[]> response) throws ApiException {
55+
submitTotalRequestsMetric(request, apiInstance, response.getStatusCode());
56+
}
57+
58+
protected static void submitTotalRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
59+
final int statusCode) throws ApiException {
4560
final String name = PREFIX + "." + CLIENT_REQUEST_TOTAL;
4661
final MetricIntakeType count = MetricIntakeType.COUNT;
47-
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, response);
62+
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, statusCode);
4863
}
4964

5065
private static void submitMetricWithHttpTags(final String name, final double value, final MetricIntakeType type,
5166
final String unit, final ApiHttpRequest request, final MetricsApi apiInstance,
5267
final ApiHttpResponse<byte[]> response) throws ApiException {
53-
final List<String> tags = Arrays.asList(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, response.getStatusCode()),
68+
submitMetricWithHttpTags(name, value, type, unit, request, apiInstance, response.getStatusCode());
69+
}
70+
71+
private static void submitMetricWithHttpTags(final String name, final double value, final MetricIntakeType type,
72+
final String unit, final ApiHttpRequest request, final MetricsApi apiInstance, final int statusCode)
73+
throws ApiException {
74+
final List<String> tags = Arrays.asList(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, statusCode),
5475
format("%s:%s", HTTP_REQUEST_METHOD, request.getMethod().name()),
5576
format("%s:%s", SERVER_ADDRESS, request.getUri().getHost()));
5677
if (request.getUri().getPort() > 0) {

commercetools/commercetools-monitoring-datadog/src/main/java/com/commercetools/monitoring/datadog/statsd/DatadogMiddleware.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import com.timgroup.statsd.StatsDClient;
1515

16+
import io.vrap.rmf.base.client.ApiHttpException;
1617
import io.vrap.rmf.base.client.ApiHttpRequest;
1718
import io.vrap.rmf.base.client.ApiHttpResponse;
1819
import io.vrap.rmf.base.client.http.TelemetryMiddleware;
@@ -49,9 +50,19 @@ public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
4950
Function<ApiHttpRequest, CompletableFuture<ApiHttpResponse<byte[]>>> next) {
5051
final Instant start = Instant.now();
5152

52-
return next.apply(request).thenApply(response -> {
53+
return next.apply(request).handle((response, throwable) -> {
5354
final List<String> tags = new ArrayList<>(4);
54-
tags.add(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, response.getStatusCode()));
55+
final int statusCode;
56+
if (response != null) {
57+
statusCode = response.getStatusCode();
58+
}
59+
else if (throwable instanceof ApiHttpException && ((ApiHttpException) throwable).getResponse() != null) {
60+
statusCode = ((ApiHttpException) throwable).getResponse().getStatusCode();
61+
}
62+
else {
63+
statusCode = 0;
64+
}
65+
tags.add(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, statusCode));
5566
tags.add(format("%s:%s", HTTP_REQUEST_METHOD, request.getMethod().name()));
5667
tags.add(format("%s:%s", SERVER_ADDRESS, request.getUri().getHost()));
5768
if (request.getUri().getPort() > 0) {
@@ -62,7 +73,7 @@ public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
6273
Duration.between(start, Instant.now()).toMillis(), tags.toArray(new String[0]));
6374

6475
this.statsDClient.incrementCounter(PREFIX + "." + CLIENT_REQUEST_TOTAL, tags.toArray(new String[0]));
65-
if (response.getStatusCode() >= 400) {
76+
if (statusCode >= 400 || throwable != null) {
6677
this.statsDClient.incrementCounter(PREFIX + "." + CLIENT_REQUEST_ERROR, tags.toArray(new String[0]));
6778
}
6879
return response;

commercetools/commercetools-monitoring-newrelic/src/main/java/com/commercetools/monitoring/newrelic/NewRelicTelemetryMiddleware.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import com.newrelic.api.agent.*;
1313

14+
import io.vrap.rmf.base.client.ApiHttpException;
1415
import io.vrap.rmf.base.client.ApiHttpRequest;
1516
import io.vrap.rmf.base.client.ApiHttpResponse;
1617
import io.vrap.rmf.base.client.ContextApiHttpClientImpl;
@@ -61,21 +62,38 @@ public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
6162
Optional<Token> token = context.map(NewRelicContext::getTransaction).map(Transaction::getToken);
6263
Optional<Segment> segment = context.map(c -> c.getTransaction()
6364
.startSegment("commercetools", request.getMethod() + " " + request.getUri().getPath()));
64-
return next.apply(request).thenApply(response -> {
65+
return next.apply(request).handle((response, throwable) -> {
6566
token.ifPresent(Token::linkAndExpire);
67+
68+
final int statusCode;
69+
final String message;
70+
if (response != null) {
71+
statusCode = response.getStatusCode();
72+
message = response.getMessage();
73+
}
74+
else if (throwable instanceof ApiHttpException && ((ApiHttpException) throwable).getResponse() != null) {
75+
ApiHttpResponse<byte[]> errorResponse = ((ApiHttpException) throwable).getResponse();
76+
statusCode = errorResponse.getStatusCode();
77+
message = errorResponse.getMessage();
78+
}
79+
else {
80+
statusCode = 0;
81+
message = throwable.getMessage();
82+
}
83+
6684
segment.ifPresent(s -> s.reportAsExternal(HttpParameters.library("commercetools-sdk-java-v2")
6785
.uri(request.getUri())
6886
.procedure(request.getMethod().name())
6987
.noInboundHeaders()
70-
.status(response.getStatusCode(), response.getMessage())
88+
.status(statusCode, message)
7189
.build()));
7290
segment.ifPresent(Segment::end);
7391

7492
NewRelic.incrementCounter(PREFIX + CLIENT_REQUEST_TOTAL);
7593
NewRelic.recordResponseTimeMetric(PREFIX + CLIENT_DURATION,
7694
Duration.between(start, Instant.now()).toMillis());
7795

78-
if (response.getStatusCode() >= 400) {
96+
if (statusCode >= 400 || throwable != null) {
7997
NewRelic.incrementCounter(PREFIX + CLIENT_REQUEST_ERROR);
8098
}
8199
return response;

commercetools/commercetools-monitoring-opentelemetry/src/main/java/com/commercetools/monitoring/opentelemetry/OpenTelemetryMiddleware.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.opentelemetry.api.metrics.LongCounter;
1414
import io.opentelemetry.api.metrics.LongHistogram;
1515
import io.opentelemetry.api.metrics.Meter;
16+
import io.vrap.rmf.base.client.ApiHttpException;
1617
import io.vrap.rmf.base.client.ApiHttpRequest;
1718
import io.vrap.rmf.base.client.ApiHttpResponse;
1819
import io.vrap.rmf.base.client.http.TelemetryMiddleware;
@@ -67,9 +68,19 @@ public OpenTelemetryMiddleware(final OpenTelemetry otel, final boolean enableHis
6768
public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
6869
Function<ApiHttpRequest, CompletableFuture<ApiHttpResponse<byte[]>>> next) {
6970
Instant start = Instant.now();
70-
return next.apply(request).thenApply(response -> {
71+
return next.apply(request).handle((response, throwable) -> {
72+
final int statusCode;
73+
if (response != null) {
74+
statusCode = response.getStatusCode();
75+
}
76+
else if (throwable instanceof ApiHttpException && ((ApiHttpException) throwable).getResponse() != null) {
77+
statusCode = ((ApiHttpException) throwable).getResponse().getStatusCode();
78+
}
79+
else {
80+
statusCode = 0;
81+
}
7182
AttributesBuilder builder = Attributes.builder()
72-
.put(OpenTelemetryInfo.HTTP_RESPONSE_STATUS_CODE, response.getStatusCode())
83+
.put(OpenTelemetryInfo.HTTP_RESPONSE_STATUS_CODE, statusCode)
7384
.put(OpenTelemetryInfo.HTTP_REQUEST_METHOD, request.getMethod().name())
7485
.put(OpenTelemetryInfo.SERVER_ADDRESS, request.getUri().getHost());
7586
if (request.getUri().getPort() > 0) {
@@ -79,7 +90,7 @@ public CompletableFuture<ApiHttpResponse<byte[]>> invoke(ApiHttpRequest request,
7990
Optional.ofNullable(histogram)
8091
.ifPresent(h -> h.record(Duration.between(start, Instant.now()).toMillis(), attributes));
8192
requestCounter.add(1, attributes);
82-
if (response.getStatusCode() >= 400) {
93+
if (statusCode >= 400 || throwable != null) {
8394
errorCounter.add(1, attributes);
8495
}
8596
return response;

0 commit comments

Comments
 (0)