Skip to content

Commit bbbc8dc

Browse files
author
Mateusz Rzeszutek
authored
Use attributes advice for HTTP & RPC metrics (#9440)
1 parent d157b68 commit bbbc8dc

File tree

13 files changed

+320
-895
lines changed

13 files changed

+320
-895
lines changed

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientExperimentalMetrics.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77

88
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpRequestBodySize;
99
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpResponseBodySize;
10-
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyClientRequestSizeView;
1110
import static java.util.logging.Level.FINE;
1211

1312
import io.opentelemetry.api.common.Attributes;
1413
import io.opentelemetry.api.metrics.LongHistogram;
14+
import io.opentelemetry.api.metrics.LongHistogramBuilder;
1515
import io.opentelemetry.api.metrics.Meter;
1616
import io.opentelemetry.context.Context;
1717
import io.opentelemetry.context.ContextKey;
@@ -49,20 +49,22 @@ public static OperationMetrics get() {
4949
private final LongHistogram responseSize;
5050

5151
private HttpClientExperimentalMetrics(Meter meter) {
52-
requestSize =
52+
LongHistogramBuilder requestSizeBuilder =
5353
meter
5454
.histogramBuilder("http.client.request.size")
5555
.setUnit("By")
5656
.setDescription("The size of HTTP request messages")
57-
.ofLongs()
58-
.build();
59-
responseSize =
57+
.ofLongs();
58+
HttpMetricsAdvice.applyClientRequestSizeAdvice(requestSizeBuilder);
59+
requestSize = requestSizeBuilder.build();
60+
LongHistogramBuilder responseSizeBuilder =
6061
meter
6162
.histogramBuilder("http.client.response.size")
6263
.setUnit("By")
6364
.setDescription("The size of HTTP response messages")
64-
.ofLongs()
65-
.build();
65+
.ofLongs();
66+
HttpMetricsAdvice.applyClientRequestSizeAdvice(responseSizeBuilder);
67+
responseSize = responseSizeBuilder.build();
6668
}
6769

6870
@Override
@@ -81,7 +83,7 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
8183
return;
8284
}
8385

84-
Attributes sizeAttributes = applyClientRequestSizeView(startAttributes, endAttributes);
86+
Attributes sizeAttributes = startAttributes.toBuilder().putAll(endAttributes).build();
8587

8688
Long requestBodySize = getHttpRequestBodySize(endAttributes, startAttributes);
8789
if (requestBodySize != null) {

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientMetrics.java

+14-16
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55

66
package io.opentelemetry.instrumentation.api.instrumenter.http;
77

8-
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMetricsUtil.createStableDurationHistogram;
9-
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyOldClientDurationView;
10-
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyStableClientDurationView;
8+
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMetricsUtil.createStableDurationHistogramBuilder;
119
import static java.util.logging.Level.FINE;
1210

1311
import com.google.auto.value.AutoValue;
1412
import io.opentelemetry.api.common.Attributes;
1513
import io.opentelemetry.api.metrics.DoubleHistogram;
14+
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
1615
import io.opentelemetry.api.metrics.Meter;
1716
import io.opentelemetry.context.Context;
1817
import io.opentelemetry.context.ContextKey;
@@ -52,19 +51,22 @@ public static OperationMetrics get() {
5251

5352
private HttpClientMetrics(Meter meter) {
5453
if (SemconvStability.emitStableHttpSemconv()) {
55-
stableDuration =
56-
createStableDurationHistogram(
54+
DoubleHistogramBuilder stableDurationBuilder =
55+
createStableDurationHistogramBuilder(
5756
meter, "http.client.request.duration", "The duration of the outbound HTTP request");
57+
HttpMetricsAdvice.applyStableClientDurationAdvice(stableDurationBuilder);
58+
stableDuration = stableDurationBuilder.build();
5859
} else {
5960
stableDuration = null;
6061
}
6162
if (SemconvStability.emitOldHttpSemconv()) {
62-
oldDuration =
63+
DoubleHistogramBuilder oldDurationBuilder =
6364
meter
6465
.histogramBuilder("http.client.duration")
6566
.setUnit("ms")
66-
.setDescription("The duration of the outbound HTTP request")
67-
.build();
67+
.setDescription("The duration of the outbound HTTP request");
68+
HttpMetricsAdvice.applyOldClientDurationAdvice(oldDurationBuilder);
69+
oldDuration = oldDurationBuilder.build();
6870
} else {
6971
oldDuration = null;
7072
}
@@ -88,18 +90,14 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
8890
return;
8991
}
9092

93+
Attributes attributes = state.startAttributes().toBuilder().putAll(endAttributes).build();
94+
9195
if (stableDuration != null) {
92-
Attributes stableDurationAttributes =
93-
applyStableClientDurationView(state.startAttributes(), endAttributes);
94-
stableDuration.record(
95-
(endNanos - state.startTimeNanos()) / NANOS_PER_S, stableDurationAttributes, context);
96+
stableDuration.record((endNanos - state.startTimeNanos()) / NANOS_PER_S, attributes, context);
9697
}
9798

9899
if (oldDuration != null) {
99-
Attributes stableDurationAttributes =
100-
applyOldClientDurationView(state.startAttributes(), endAttributes);
101-
oldDuration.record(
102-
(endNanos - state.startTimeNanos()) / NANOS_PER_MS, stableDurationAttributes, context);
100+
oldDuration.record((endNanos - state.startTimeNanos()) / NANOS_PER_MS, attributes, context);
103101
}
104102
}
105103

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.instrumenter.http;
7+
8+
import static java.util.Arrays.asList;
9+
10+
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
11+
import io.opentelemetry.api.metrics.LongHistogramBuilder;
12+
import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
13+
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder;
14+
import io.opentelemetry.extension.incubator.metrics.ExtendedLongHistogramBuilder;
15+
import io.opentelemetry.extension.incubator.metrics.ExtendedLongUpDownCounterBuilder;
16+
import io.opentelemetry.instrumentation.api.instrumenter.http.internal.HttpAttributes;
17+
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
18+
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
19+
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
20+
21+
final class HttpMetricsAdvice {
22+
23+
static void applyStableClientDurationAdvice(DoubleHistogramBuilder builder) {
24+
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
25+
return;
26+
}
27+
((ExtendedDoubleHistogramBuilder) builder)
28+
.setAdvice(
29+
advice ->
30+
advice.setAttributes(
31+
asList(
32+
HttpAttributes.HTTP_REQUEST_METHOD,
33+
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
34+
NetworkAttributes.NETWORK_PROTOCOL_NAME,
35+
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
36+
NetworkAttributes.SERVER_ADDRESS,
37+
NetworkAttributes.SERVER_PORT,
38+
NetworkAttributes.SERVER_SOCKET_ADDRESS)));
39+
}
40+
41+
static void applyOldClientDurationAdvice(DoubleHistogramBuilder builder) {
42+
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
43+
return;
44+
}
45+
((ExtendedDoubleHistogramBuilder) builder)
46+
.setAdvice(
47+
advice ->
48+
advice.setAttributes(
49+
asList(
50+
SemanticAttributes.HTTP_METHOD,
51+
SemanticAttributes.HTTP_STATUS_CODE,
52+
SemanticAttributes.NET_PEER_NAME,
53+
SemanticAttributes.NET_PEER_PORT,
54+
SemanticAttributes.NET_PROTOCOL_NAME,
55+
SemanticAttributes.NET_PROTOCOL_VERSION,
56+
SemanticAttributes.NET_SOCK_PEER_ADDR)));
57+
}
58+
59+
static void applyClientRequestSizeAdvice(LongHistogramBuilder builder) {
60+
if (!(builder instanceof ExtendedLongHistogramBuilder)) {
61+
return;
62+
}
63+
((ExtendedLongHistogramBuilder) builder)
64+
.setAdvice(
65+
advice ->
66+
advice.setAttributes(
67+
asList(
68+
// stable attributes
69+
HttpAttributes.HTTP_REQUEST_METHOD,
70+
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
71+
NetworkAttributes.NETWORK_PROTOCOL_NAME,
72+
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
73+
NetworkAttributes.SERVER_ADDRESS,
74+
NetworkAttributes.SERVER_PORT,
75+
NetworkAttributes.SERVER_SOCKET_ADDRESS,
76+
// old attributes
77+
SemanticAttributes.HTTP_METHOD,
78+
SemanticAttributes.HTTP_STATUS_CODE,
79+
SemanticAttributes.NET_PEER_NAME,
80+
SemanticAttributes.NET_PEER_PORT,
81+
SemanticAttributes.NET_PROTOCOL_NAME,
82+
SemanticAttributes.NET_PROTOCOL_VERSION,
83+
SemanticAttributes.NET_SOCK_PEER_ADDR)));
84+
}
85+
86+
static void applyStableServerDurationAdvice(DoubleHistogramBuilder builder) {
87+
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
88+
return;
89+
}
90+
((ExtendedDoubleHistogramBuilder) builder)
91+
.setAdvice(
92+
advice ->
93+
advice.setAttributes(
94+
asList(
95+
SemanticAttributes.HTTP_ROUTE,
96+
HttpAttributes.HTTP_REQUEST_METHOD,
97+
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
98+
NetworkAttributes.NETWORK_PROTOCOL_NAME,
99+
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
100+
UrlAttributes.URL_SCHEME)));
101+
}
102+
103+
static void applyOldServerDurationAdvice(DoubleHistogramBuilder builder) {
104+
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
105+
return;
106+
}
107+
((ExtendedDoubleHistogramBuilder) builder)
108+
.setAdvice(
109+
advice ->
110+
advice.setAttributes(
111+
asList(
112+
SemanticAttributes.HTTP_SCHEME,
113+
SemanticAttributes.HTTP_ROUTE,
114+
SemanticAttributes.HTTP_METHOD,
115+
SemanticAttributes.HTTP_STATUS_CODE,
116+
SemanticAttributes.NET_HOST_NAME,
117+
SemanticAttributes.NET_HOST_PORT,
118+
SemanticAttributes.NET_PROTOCOL_NAME,
119+
SemanticAttributes.NET_PROTOCOL_VERSION)));
120+
}
121+
122+
static void applyServerRequestSizeAdvice(LongHistogramBuilder builder) {
123+
if (!(builder instanceof ExtendedLongHistogramBuilder)) {
124+
return;
125+
}
126+
((ExtendedLongHistogramBuilder) builder)
127+
.setAdvice(
128+
advice ->
129+
advice.setAttributes(
130+
asList(
131+
// stable attributes
132+
SemanticAttributes.HTTP_ROUTE,
133+
HttpAttributes.HTTP_REQUEST_METHOD,
134+
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
135+
NetworkAttributes.NETWORK_PROTOCOL_NAME,
136+
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
137+
UrlAttributes.URL_SCHEME,
138+
// old attributes
139+
SemanticAttributes.HTTP_SCHEME,
140+
SemanticAttributes.HTTP_ROUTE,
141+
SemanticAttributes.HTTP_METHOD,
142+
SemanticAttributes.HTTP_STATUS_CODE,
143+
SemanticAttributes.NET_HOST_NAME,
144+
SemanticAttributes.NET_HOST_PORT,
145+
SemanticAttributes.NET_PROTOCOL_NAME,
146+
SemanticAttributes.NET_PROTOCOL_VERSION)));
147+
}
148+
149+
static void applyServerActiveRequestsAdvice(LongUpDownCounterBuilder builder) {
150+
if (!(builder instanceof ExtendedLongUpDownCounterBuilder)) {
151+
return;
152+
}
153+
((ExtendedLongUpDownCounterBuilder) builder)
154+
.setAdvice(
155+
advice ->
156+
advice.setAttributes(
157+
asList(
158+
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpserveractive_requests
159+
SemanticAttributes.HTTP_METHOD,
160+
SemanticAttributes.HTTP_SCHEME,
161+
SemanticAttributes.NET_HOST_NAME,
162+
SemanticAttributes.NET_HOST_PORT,
163+
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserveractive_requests
164+
HttpAttributes.HTTP_REQUEST_METHOD,
165+
UrlAttributes.URL_SCHEME)));
166+
}
167+
168+
private HttpMetricsAdvice() {}
169+
}

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpMetricsUtil.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import static java.util.Arrays.asList;
99
import static java.util.Collections.unmodifiableList;
1010

11-
import io.opentelemetry.api.metrics.DoubleHistogram;
1211
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
1312
import io.opentelemetry.api.metrics.Meter;
1413
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder;
@@ -22,7 +21,7 @@ final class HttpMetricsUtil {
2221
0.0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5,
2322
10.0));
2423

25-
static DoubleHistogram createStableDurationHistogram(
24+
static DoubleHistogramBuilder createStableDurationHistogramBuilder(
2625
Meter meter, String name, String description) {
2726
DoubleHistogramBuilder durationBuilder =
2827
meter.histogramBuilder(name).setUnit("s").setDescription(description);
@@ -31,7 +30,7 @@ static DoubleHistogram createStableDurationHistogram(
3130
((ExtendedDoubleHistogramBuilder) durationBuilder)
3231
.setAdvice(advice -> advice.setExplicitBucketBoundaries(DURATION_SECONDS_BUCKETS));
3332
}
34-
return durationBuilder.build();
33+
return durationBuilder;
3534
}
3635

3736
private HttpMetricsUtil() {}

instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpServerExperimentalMetrics.java

+17-14
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpRequestBodySize;
99
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpResponseBodySize;
10-
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyActiveRequestsView;
11-
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyServerRequestSizeView;
1210
import static java.util.logging.Level.FINE;
1311

1412
import io.opentelemetry.api.common.Attributes;
1513
import io.opentelemetry.api.metrics.LongHistogram;
14+
import io.opentelemetry.api.metrics.LongHistogramBuilder;
1615
import io.opentelemetry.api.metrics.LongUpDownCounter;
16+
import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
1717
import io.opentelemetry.api.metrics.Meter;
1818
import io.opentelemetry.context.Context;
1919
import io.opentelemetry.context.ContextKey;
@@ -54,31 +54,34 @@ public static OperationMetrics get() {
5454
private final LongHistogram responseSize;
5555

5656
private HttpServerExperimentalMetrics(Meter meter) {
57-
activeRequests =
57+
LongUpDownCounterBuilder activeRequestsBuilder =
5858
meter
5959
.upDownCounterBuilder("http.server.active_requests")
6060
.setUnit("{requests}")
61-
.setDescription("The number of concurrent HTTP requests that are currently in-flight")
62-
.build();
63-
requestSize =
61+
.setDescription("The number of concurrent HTTP requests that are currently in-flight");
62+
HttpMetricsAdvice.applyServerActiveRequestsAdvice(activeRequestsBuilder);
63+
activeRequests = activeRequestsBuilder.build();
64+
LongHistogramBuilder requestSizeBuilder =
6465
meter
6566
.histogramBuilder("http.server.request.size")
6667
.setUnit("By")
6768
.setDescription("The size of HTTP request messages")
68-
.ofLongs()
69-
.build();
70-
responseSize =
69+
.ofLongs();
70+
HttpMetricsAdvice.applyServerRequestSizeAdvice(requestSizeBuilder);
71+
requestSize = requestSizeBuilder.build();
72+
LongHistogramBuilder responseSizeBuilder =
7173
meter
7274
.histogramBuilder("http.server.response.size")
7375
.setUnit("By")
7476
.setDescription("The size of HTTP response messages")
75-
.ofLongs()
76-
.build();
77+
.ofLongs();
78+
HttpMetricsAdvice.applyServerRequestSizeAdvice(responseSizeBuilder);
79+
responseSize = responseSizeBuilder.build();
7780
}
7881

7982
@Override
8083
public Context onStart(Context context, Attributes startAttributes, long startNanos) {
81-
activeRequests.add(1, applyActiveRequestsView(startAttributes), context);
84+
activeRequests.add(1, startAttributes, context);
8285

8386
return context.with(HTTP_SERVER_EXPERIMENTAL_METRICS_START_ATTRIBUTES, startAttributes);
8487
}
@@ -95,9 +98,9 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
9598
}
9699
// it's important to use exactly the same attributes that were used when incrementing the active
97100
// request count (otherwise it will split the timeseries)
98-
activeRequests.add(-1, applyActiveRequestsView(startAttributes), context);
101+
activeRequests.add(-1, startAttributes, context);
99102

100-
Attributes sizeAttributes = applyServerRequestSizeView(startAttributes, endAttributes);
103+
Attributes sizeAttributes = startAttributes.toBuilder().putAll(endAttributes).build();
101104

102105
Long requestBodySize = getHttpRequestBodySize(endAttributes, startAttributes);
103106
if (requestBodySize != null) {

0 commit comments

Comments
 (0)