Skip to content

Commit a18fbcd

Browse files
committed
support custom attributes for metrics
1 parent 1defd11 commit a18fbcd

File tree

11 files changed

+320
-62
lines changed

11 files changed

+320
-62
lines changed

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
package com.commercetools.monitoring.datadog;
33

44
import static com.commercetools.monitoring.datadog.DatadogUtils.*;
5+
import static java.lang.String.format;
56

67
import java.time.Duration;
78
import java.time.Instant;
9+
import java.util.Collection;
10+
import java.util.Collections;
11+
import java.util.Map;
812
import java.util.concurrent.CompletableFuture;
913
import java.util.function.Function;
14+
import java.util.stream.Collectors;
1015

1116
import com.datadog.api.client.ApiClient;
1217
import com.datadog.api.client.ApiException;
@@ -40,12 +45,24 @@ public class DatadogMiddleware implements TelemetryMiddleware {
4045

4146
private final MetricsApi apiInstance;
4247

48+
private final Collection<String> tags;
49+
4350
public DatadogMiddleware(final ApiClient ddApiClient) {
44-
this.apiInstance = new MetricsApi(ddApiClient);
51+
this(new MetricsApi(ddApiClient));
52+
}
53+
54+
public DatadogMiddleware(final ApiClient ddApiClient, final Map<String, String> tags) {
55+
this(new MetricsApi(ddApiClient), tags);
4556
}
4657

4758
public DatadogMiddleware(final MetricsApi apiInstance) {
59+
this(apiInstance, Collections.emptyMap());
60+
}
61+
62+
public DatadogMiddleware(final MetricsApi apiInstance, final Map<String, String> tags) {
4863
this.apiInstance = apiInstance;
64+
this.tags = tags.entrySet().stream().map(entry -> format("%s:%s", entry.getKey(), entry.getValue())).collect(
65+
Collectors.toList());
4966
}
5067

5168
@Override
@@ -65,10 +82,10 @@ else if (throwable instanceof ApiHttpException && ((ApiHttpException) throwable)
6582
}
6683
try {
6784
submitClientDurationMetric(request, apiInstance, Duration.between(start, Instant.now()).toMillis(),
68-
statusCode);
69-
submitTotalRequestsMetric(request, apiInstance, statusCode);
85+
statusCode, tags);
86+
submitTotalRequestsMetric(request, apiInstance, statusCode, tags);
7087
if (statusCode >= 400 || throwable != null) {
71-
submitErrorRequestsMetric(request, apiInstance, statusCode);
88+
submitErrorRequestsMetric(request, apiInstance, statusCode, tags);
7289
}
7390
}
7491
catch (ApiException e) {

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

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,14 @@
33

44
import static com.commercetools.monitoring.datadog.DatadogUtils.submitJsonDeserializationMetric;
55
import static com.commercetools.monitoring.datadog.DatadogUtils.submitJsonSerializationMetric;
6+
import static java.lang.String.format;
67

78
import java.time.Duration;
89
import java.time.Instant;
10+
import java.util.Collection;
11+
import java.util.Collections;
12+
import java.util.Map;
13+
import java.util.stream.Collectors;
914

1015
import com.datadog.api.client.ApiClient;
1116
import com.datadog.api.client.v2.api.MetricsApi;
@@ -25,22 +30,33 @@ public class DatadogResponseSerializer implements ResponseSerializer {
2530

2631
private final MetricsApi apiInstance;
2732

28-
public DatadogResponseSerializer(final ResponseSerializer serializer, final MetricsApi apiInstance) {
33+
private final Collection<String> tags;
34+
35+
36+
public DatadogResponseSerializer(final ResponseSerializer serializer, final MetricsApi apiInstance, final Map<String, String> tags) {
2937
this.serializer = serializer;
3038
this.apiInstance = apiInstance;
39+
this.tags = tags.entrySet().stream().map(entry -> format("%s:%s", entry.getKey(), entry.getValue())).collect(
40+
Collectors.toList());
41+
}
42+
43+
public DatadogResponseSerializer(final ResponseSerializer serializer, final MetricsApi apiInstance) {
44+
this(serializer, apiInstance, Collections.emptyMap());
3145
}
3246

47+
public DatadogResponseSerializer(final ResponseSerializer serializer, final ApiClient ddApiClient, final Map<String, String> tags) {
48+
this(serializer, new MetricsApi(ddApiClient), tags);
49+
}
3350
public DatadogResponseSerializer(final ResponseSerializer serializer, final ApiClient ddApiClient) {
34-
this.serializer = serializer;
35-
this.apiInstance = new MetricsApi(ddApiClient);
51+
this(serializer, new MetricsApi(ddApiClient), Collections.emptyMap());
3652
}
3753

3854
@Override
3955
public <O> ApiHttpResponse<O> convertResponse(ApiHttpResponse<byte[]> response, Class<O> outputType) {
4056
Instant start = Instant.now();
4157
ApiHttpResponse<O> result = serializer.convertResponse(response, outputType);
4258
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
43-
submitJsonDeserializationMetric(apiInstance, (double) durationInMillis, outputType.getCanonicalName());
59+
submitJsonDeserializationMetric(apiInstance, (double) durationInMillis, outputType.getCanonicalName(), tags);
4460
return result;
4561
}
4662

@@ -49,7 +65,7 @@ public <O> ApiHttpResponse<O> convertResponse(ApiHttpResponse<byte[]> response,
4965
Instant start = Instant.now();
5066
ApiHttpResponse<O> result = serializer.convertResponse(response, outputType);
5167
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
52-
submitJsonDeserializationMetric(apiInstance, durationInMillis, outputType.toString());
68+
submitJsonDeserializationMetric(apiInstance, durationInMillis, outputType.toString(), tags);
5369
return result;
5470
}
5571

@@ -58,7 +74,7 @@ public <O> ApiHttpResponse<O> convertResponse(ApiHttpResponse<byte[]> response,
5874
Instant start = Instant.now();
5975
ApiHttpResponse<O> result = serializer.convertResponse(response, outputType);
6076
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
61-
submitJsonDeserializationMetric(apiInstance, durationInMillis, outputType.getType().getTypeName());
77+
submitJsonDeserializationMetric(apiInstance, durationInMillis, outputType.getType().getTypeName(), tags);
6278
return result;
6379
}
6480

@@ -67,7 +83,7 @@ public byte[] toJsonByteArray(Object value) throws JsonProcessingException {
6783
Instant start = Instant.now();
6884
byte[] result = serializer.toJsonByteArray(value);
6985
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
70-
submitJsonSerializationMetric(apiInstance, durationInMillis, value.getClass().getCanonicalName());
86+
submitJsonSerializationMetric(apiInstance, durationInMillis, value.getClass().getCanonicalName(), tags);
7187
return result;
7288
}
7389

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

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
import static java.lang.String.format;
66

77
import java.time.OffsetDateTime;
8-
import java.util.Arrays;
9-
import java.util.Collections;
10-
import java.util.List;
8+
import java.util.*;
119

1210
import com.datadog.api.client.ApiException;
1311
import com.datadog.api.client.v2.api.MetricsApi;
@@ -27,75 +25,81 @@ public class DatadogUtils {
2725
private static final Logger logger = LoggerFactory.getLogger(DatadogMiddleware.class);
2826

2927
protected static void submitClientDurationMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
30-
final double durationInMillis, final ApiHttpResponse<byte[]> response) throws ApiException {
31-
submitClientDurationMetric(request, apiInstance, durationInMillis, response.getStatusCode());
28+
final double durationInMillis, final ApiHttpResponse<byte[]> response, final Collection<String> tags) throws ApiException {
29+
submitClientDurationMetric(request, apiInstance, durationInMillis, response.getStatusCode(), tags);
3230
}
3331

3432
protected static void submitClientDurationMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
35-
final double durationInMillis, final int statusCode) throws ApiException {
33+
final double durationInMillis, final int statusCode, final Collection<String> tags) throws ApiException {
3634
final String name = PREFIX + "." + CLIENT_DURATION;
3735
final MetricIntakeType type = MetricIntakeType.UNSPECIFIED;
38-
submitMetricWithHttpTags(name, durationInMillis, type, "ms", request, apiInstance, statusCode);
36+
submitMetricWithHttpTags(name, durationInMillis, type, "ms", request, apiInstance, statusCode, tags);
3937
}
4038

4139
protected static void submitErrorRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
42-
final ApiHttpResponse<byte[]> response) throws ApiException {
43-
submitErrorRequestsMetric(request, apiInstance, response.getStatusCode());
40+
final ApiHttpResponse<byte[]> response, final Collection<String> tags) throws ApiException {
41+
submitErrorRequestsMetric(request, apiInstance, response.getStatusCode(), tags);
4442
}
4543

4644
protected static void submitErrorRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
47-
final int statusCode) throws ApiException {
45+
final int statusCode, final Collection<String> tags) throws ApiException {
4846
final String name = PREFIX + "." + CLIENT_REQUEST_ERROR;
4947
final MetricIntakeType count = MetricIntakeType.COUNT;
50-
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, statusCode);
48+
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, statusCode, tags);
5149
}
5250

5351
protected static void submitTotalRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
54-
final ApiHttpResponse<byte[]> response) throws ApiException {
55-
submitTotalRequestsMetric(request, apiInstance, response.getStatusCode());
52+
final ApiHttpResponse<byte[]> response, final Collection<String> tags) throws ApiException {
53+
submitTotalRequestsMetric(request, apiInstance, response.getStatusCode(), tags);
5654
}
5755

5856
protected static void submitTotalRequestsMetric(final ApiHttpRequest request, final MetricsApi apiInstance,
59-
final int statusCode) throws ApiException {
57+
final int statusCode, final Collection<String> tags) throws ApiException {
6058
final String name = PREFIX + "." + CLIENT_REQUEST_TOTAL;
6159
final MetricIntakeType count = MetricIntakeType.COUNT;
62-
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, statusCode);
60+
submitMetricWithHttpTags(name, 1.0, count, "count", request, apiInstance, statusCode, tags);
6361
}
6462

6563
private static void submitMetricWithHttpTags(final String name, final double value, final MetricIntakeType type,
6664
final String unit, final ApiHttpRequest request, final MetricsApi apiInstance,
67-
final ApiHttpResponse<byte[]> response) throws ApiException {
68-
submitMetricWithHttpTags(name, value, type, unit, request, apiInstance, response.getStatusCode());
65+
final ApiHttpResponse<byte[]> response, final Collection<String> tags) throws ApiException {
66+
submitMetricWithHttpTags(name, value, type, unit, request, apiInstance, response.getStatusCode(), tags);
6967
}
7068

7169
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)
70+
final String unit, final ApiHttpRequest request, final MetricsApi apiInstance, final int statusCode, final Collection<String> tags)
7371
throws ApiException {
74-
final List<String> tags = Arrays.asList(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, statusCode),
75-
format("%s:%s", HTTP_REQUEST_METHOD, request.getMethod().name()),
76-
format("%s:%s", SERVER_ADDRESS, request.getUri().getHost()));
72+
final List<String> currentTags = new ArrayList<>(tags);
73+
currentTags.add(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, statusCode));
74+
currentTags.add(format("%s:%s", HTTP_REQUEST_METHOD, request.getMethod().name()));
75+
currentTags.add(format("%s:%s", SERVER_ADDRESS, request.getUri().getHost()));
7776
if (request.getUri().getPort() > 0) {
78-
tags.add(format("%s:%s", SERVER_PORT, request.getUri().getPort()));
77+
currentTags.add(format("%s:%s", SERVER_PORT, request.getUri().getPort()));
7978
}
80-
submitMetric(apiInstance, name, value, type, unit, tags);
79+
submitMetric(apiInstance, name, value, type, unit, currentTags);
8180
}
8281

8382
protected static void submitJsonSerializationMetric(final MetricsApi apiInstance, final double durationInMillis,
84-
final String responseBodyType) {
83+
final String responseBodyType, final Collection<String> tags) {
8584
try {
85+
final List<String> currentTags = new ArrayList<>(tags);
86+
currentTags.add(format("%s:%s", RESPONSE_BODY_TYPE, responseBodyType));
8687
submitMetric(apiInstance, PREFIX + "." + JSON_SERIALIZATION, durationInMillis, MetricIntakeType.UNSPECIFIED,
87-
"ms", Arrays.asList(format("%s:%s", RESPONSE_BODY_TYPE, responseBodyType)));
88+
"ms", currentTags);
8889
}
8990
catch (ApiException exception) {
9091
logger.warn("Failed to submit commercetools json serialization metric", exception);
9192
}
9293
}
9394

9495
protected static void submitJsonDeserializationMetric(final MetricsApi apiInstance, final double durationInMillis,
95-
final String requestBodyType) {
96+
final String requestBodyType, final Collection<String> tags) {
9697
try {
98+
final List<String> currentTags = new ArrayList<>(tags);
99+
currentTags.add(format("%s:%s", REQUEST_BODY_TYPE, requestBodyType));
100+
97101
submitMetric(apiInstance, PREFIX + "." + JSON_DESERIALIZATION, durationInMillis,
98-
MetricIntakeType.UNSPECIFIED, "ms", Arrays.asList(format("%s:%s", REQUEST_BODY_TYPE, requestBodyType)));
102+
MetricIntakeType.UNSPECIFIED, "ms", currentTags);
99103
}
100104
catch (ApiException exception) {
101105
logger.warn("Failed to submit commercetools json deserialization metric", exception);

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import java.time.Duration;
88
import java.time.Instant;
9-
import java.util.ArrayList;
10-
import java.util.List;
9+
import java.util.*;
1110
import java.util.concurrent.CompletableFuture;
1211
import java.util.function.Function;
12+
import java.util.stream.Collectors;
1313

1414
import com.timgroup.statsd.StatsDClient;
1515

@@ -41,8 +41,17 @@ public class DatadogMiddleware implements TelemetryMiddleware {
4141

4242
private final StatsDClient statsDClient;
4343

44+
private final Collection<String> tags;
45+
4446
public DatadogMiddleware(final StatsDClient datadogStatsDClient) {
4547
this.statsDClient = datadogStatsDClient;
48+
this.tags = Collections.emptyList();
49+
}
50+
51+
public DatadogMiddleware(final StatsDClient datadogStatsDClient, final Map<String, String> tags) {
52+
this.statsDClient = datadogStatsDClient;
53+
this.tags = tags.entrySet().stream().map(entry -> format("%s:%s", entry.getKey(), entry.getValue())).collect(
54+
Collectors.toList());
4655
}
4756

4857
@Override
@@ -65,6 +74,7 @@ else if (throwable instanceof ApiHttpException && ((ApiHttpException) throwable)
6574
tags.add(format("%s:%s", HTTP_RESPONSE_STATUS_CODE, statusCode));
6675
tags.add(format("%s:%s", HTTP_REQUEST_METHOD, request.getMethod().name()));
6776
tags.add(format("%s:%s", SERVER_ADDRESS, request.getUri().getHost()));
77+
tags.addAll(this.tags);
6878
if (request.getUri().getPort() > 0) {
6979
tags.add(format("%s:%s", SERVER_PORT, request.getUri().getPort()));
7080
}

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

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
import java.time.Duration;
88
import java.time.Instant;
9+
import java.util.*;
10+
import java.util.stream.Collectors;
911

1012
import com.fasterxml.jackson.core.JsonProcessingException;
1113
import com.fasterxml.jackson.core.type.TypeReference;
@@ -24,18 +26,32 @@ public class DatadogResponseSerializer implements ResponseSerializer {
2426

2527
private final StatsDClient statsDClient;
2628

29+
private final Collection<String> tags;
30+
31+
2732
public DatadogResponseSerializer(final ResponseSerializer serializer, final StatsDClient datadogStatsDClient) {
2833
this.serializer = serializer;
2934
this.statsDClient = datadogStatsDClient;
35+
this.tags = Collections.emptyList();
36+
}
37+
38+
public DatadogResponseSerializer(final ResponseSerializer serializer, final StatsDClient datadogStatsDClient, final Map<String, String> tags) {
39+
this.serializer = serializer;
40+
this.statsDClient = datadogStatsDClient;
41+
this.tags = tags.entrySet().stream().map(entry -> format("%s:%s", entry.getKey(), entry.getValue())).collect(
42+
Collectors.toList());
3043
}
3144

45+
3246
@Override
3347
public <O> ApiHttpResponse<O> convertResponse(ApiHttpResponse<byte[]> response, Class<O> outputType) {
3448
Instant start = Instant.now();
3549
ApiHttpResponse<O> result = serializer.convertResponse(response, outputType);
3650
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
37-
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_DESERIALIZATION, durationInMillis,
38-
format("%s:%s", RESPONSE_BODY_TYPE, outputType.getCanonicalName()));
51+
final Collection<String> tags = new ArrayList<>(this.tags);
52+
tags.add(format("%s:%s", RESPONSE_BODY_TYPE, outputType.getCanonicalName()));
53+
54+
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_DESERIALIZATION, durationInMillis, tags.toArray(new String[0]));
3955
return result;
4056
}
4157

@@ -44,8 +60,10 @@ public <O> ApiHttpResponse<O> convertResponse(ApiHttpResponse<byte[]> response,
4460
Instant start = Instant.now();
4561
ApiHttpResponse<O> result = serializer.convertResponse(response, outputType);
4662
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
47-
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_DESERIALIZATION, durationInMillis,
48-
format("%s:%s", RESPONSE_BODY_TYPE, outputType.toString()));
63+
final Collection<String> tags = new ArrayList<>(this.tags);
64+
tags.add(format("%s:%s", RESPONSE_BODY_TYPE, outputType.toString()));
65+
66+
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_DESERIALIZATION, durationInMillis, tags.toArray(new String[0]));
4967
return result;
5068
}
5169

@@ -54,8 +72,10 @@ public <O> ApiHttpResponse<O> convertResponse(ApiHttpResponse<byte[]> response,
5472
Instant start = Instant.now();
5573
ApiHttpResponse<O> result = serializer.convertResponse(response, outputType);
5674
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
57-
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_DESERIALIZATION, durationInMillis,
58-
format("%s:%s", RESPONSE_BODY_TYPE, outputType.getType().getTypeName()));
75+
final Collection<String> tags = new ArrayList<>(this.tags);
76+
tags.add(format("%s:%s", RESPONSE_BODY_TYPE, outputType.getType().getTypeName()));
77+
78+
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_DESERIALIZATION, durationInMillis, tags.toArray(new String[0]));
5979
return result;
6080
}
6181

@@ -64,8 +84,10 @@ public byte[] toJsonByteArray(Object value) throws JsonProcessingException {
6484
Instant start = Instant.now();
6585
byte[] result = serializer.toJsonByteArray(value);
6686
double durationInMillis = Duration.between(start, Instant.now()).toNanos() / 1_000_000.0;
67-
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_SERIALIZATION, durationInMillis,
68-
format("%s:%s", REQUEST_BODY_TYPE, value.getClass().getCanonicalName()));
87+
final Collection<String> tags = new ArrayList<>(this.tags);
88+
tags.add(format("%s:%s", RESPONSE_BODY_TYPE, value.getClass().getCanonicalName()));
89+
90+
this.statsDClient.recordHistogramValue(PREFIX + "." + JSON_SERIALIZATION, durationInMillis, tags.toArray(new String[0]));
6991
return result;
7092
}
7193

0 commit comments

Comments
 (0)