Skip to content

Commit 133de24

Browse files
author
Mateusz Rzeszutek
authored
Extract HTTP server experimental metrics to a separate class (#9259)
1 parent bcd693f commit 133de24

File tree

30 files changed

+956
-447
lines changed

30 files changed

+956
-447
lines changed

CHANGELOG.md

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

33
## Unreleased
44

5+
### Migration notes
6+
7+
- Experimental HTTP server metrics have been split out from `HttpServerMetrics` into a separate
8+
class `HttpServerExperimentalMetrics`
9+
([#9259](https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/9259))
10+
511
## Version 1.29.0 (2023-08-17)
612

713
### Migration notes

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-client">non-stable
2525
* HTTP client metrics</a>: <a
2626
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/specification/metrics/semantic_conventions/http-metrics.md#metric-httpclientrequestsize">the
27-
* request size </a> and the <a
27+
* request size </a> and <a
2828
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/specification/metrics/semantic_conventions/http-metrics.md#metric-httpclientresponsesize">
2929
* the response size</a>.
3030
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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 io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpRequestBodySize;
9+
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.applyServerDurationAndSizeView;
12+
import static java.util.logging.Level.FINE;
13+
14+
import io.opentelemetry.api.common.Attributes;
15+
import io.opentelemetry.api.metrics.LongHistogram;
16+
import io.opentelemetry.api.metrics.LongUpDownCounter;
17+
import io.opentelemetry.api.metrics.Meter;
18+
import io.opentelemetry.context.Context;
19+
import io.opentelemetry.context.ContextKey;
20+
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
21+
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
22+
import java.util.logging.Logger;
23+
24+
/**
25+
* {@link OperationListener} which keeps track of <a
26+
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/specification/metrics/semantic_conventions/http-metrics.md#http-server">non-stable
27+
* HTTP server metrics</a>: <a
28+
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserveractive_requests">the
29+
* number of in-flight request</a>, <a
30+
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverrequestsize">the
31+
* request size</a> and <a
32+
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverresponsesize">the
33+
* response size</a>.
34+
*/
35+
public final class HttpServerExperimentalMetrics implements OperationListener {
36+
37+
private static final ContextKey<Attributes> HTTP_SERVER_EXPERIMENTAL_METRICS_START_ATTRIBUTES =
38+
ContextKey.named("http-server-experimental-metrics-start-attributes");
39+
40+
private static final Logger logger =
41+
Logger.getLogger(HttpServerExperimentalMetrics.class.getName());
42+
43+
/**
44+
* Returns a {@link OperationMetrics} which can be used to enable recording of {@link
45+
* HttpServerExperimentalMetrics} on an {@link
46+
* io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder}.
47+
*/
48+
public static OperationMetrics get() {
49+
return HttpServerExperimentalMetrics::new;
50+
}
51+
52+
private final LongUpDownCounter activeRequests;
53+
private final LongHistogram requestSize;
54+
private final LongHistogram responseSize;
55+
56+
private HttpServerExperimentalMetrics(Meter meter) {
57+
activeRequests =
58+
meter
59+
.upDownCounterBuilder("http.server.active_requests")
60+
.setUnit("{requests}")
61+
.setDescription("The number of concurrent HTTP requests that are currently in-flight")
62+
.build();
63+
requestSize =
64+
meter
65+
.histogramBuilder("http.server.request.size")
66+
.setUnit("By")
67+
.setDescription("The size of HTTP request messages")
68+
.ofLongs()
69+
.build();
70+
responseSize =
71+
meter
72+
.histogramBuilder("http.server.response.size")
73+
.setUnit("By")
74+
.setDescription("The size of HTTP response messages")
75+
.ofLongs()
76+
.build();
77+
}
78+
79+
@Override
80+
public Context onStart(Context context, Attributes startAttributes, long startNanos) {
81+
activeRequests.add(1, applyActiveRequestsView(startAttributes), context);
82+
83+
return context.with(HTTP_SERVER_EXPERIMENTAL_METRICS_START_ATTRIBUTES, startAttributes);
84+
}
85+
86+
@Override
87+
public void onEnd(Context context, Attributes endAttributes, long endNanos) {
88+
Attributes startAttributes = context.get(HTTP_SERVER_EXPERIMENTAL_METRICS_START_ATTRIBUTES);
89+
if (startAttributes == null) {
90+
logger.log(
91+
FINE,
92+
"No state present when ending context {0}. Cannot record HTTP request metrics.",
93+
context);
94+
return;
95+
}
96+
// it's important to use exactly the same attributes that were used when incrementing the active
97+
// request count (otherwise it will split the timeseries)
98+
activeRequests.add(-1, applyActiveRequestsView(startAttributes), context);
99+
100+
Attributes sizeAttributes = applyServerDurationAndSizeView(startAttributes, endAttributes);
101+
102+
Long requestBodySize = getHttpRequestBodySize(endAttributes, startAttributes);
103+
if (requestBodySize != null) {
104+
requestSize.record(requestBodySize, sizeAttributes, context);
105+
}
106+
107+
Long responseBodySize = getHttpResponseBodySize(endAttributes, startAttributes);
108+
if (responseBodySize != null) {
109+
responseSize.record(responseBodySize, sizeAttributes, context);
110+
}
111+
}
112+
}

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

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,14 @@
55

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

8-
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpRequestBodySize;
9-
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpResponseBodySize;
108
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMetricsUtil.createDurationHistogram;
119
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMetricsUtil.nanosToUnit;
12-
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyActiveRequestsView;
1310
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyServerDurationAndSizeView;
1411
import static java.util.logging.Level.FINE;
1512

1613
import com.google.auto.value.AutoValue;
1714
import io.opentelemetry.api.common.Attributes;
1815
import io.opentelemetry.api.metrics.DoubleHistogram;
19-
import io.opentelemetry.api.metrics.LongHistogram;
20-
import io.opentelemetry.api.metrics.LongUpDownCounter;
2116
import io.opentelemetry.api.metrics.Meter;
2217
import io.opentelemetry.context.Context;
2318
import io.opentelemetry.context.ContextKey;
@@ -32,8 +27,8 @@
3227
*/
3328
public final class HttpServerMetrics implements OperationListener {
3429

35-
private static final ContextKey<State> HTTP_SERVER_REQUEST_METRICS_STATE =
36-
ContextKey.named("http-server-request-metrics-state");
30+
private static final ContextKey<State> HTTP_SERVER_METRICS_STATE =
31+
ContextKey.named("http-server-metrics-state");
3732

3833
private static final Logger logger = Logger.getLogger(HttpServerMetrics.class.getName());
3934

@@ -46,78 +41,39 @@ public static OperationMetrics get() {
4641
return HttpServerMetrics::new;
4742
}
4843

49-
private final LongUpDownCounter activeRequests;
5044
private final DoubleHistogram duration;
51-
private final LongHistogram requestSize;
52-
private final LongHistogram responseSize;
5345

5446
private HttpServerMetrics(Meter meter) {
55-
activeRequests =
56-
meter
57-
.upDownCounterBuilder("http.server.active_requests")
58-
.setUnit("{requests}")
59-
.setDescription("The number of concurrent HTTP requests that are currently in-flight")
60-
.build();
6147
String durationInstrumentName =
6248
HttpMetricsUtil.emitNewSemconvMetrics
6349
? "http.server.request.duration"
6450
: "http.server.duration";
6551
duration =
6652
createDurationHistogram(
6753
meter, durationInstrumentName, "The duration of the inbound HTTP request");
68-
requestSize =
69-
meter
70-
.histogramBuilder("http.server.request.size")
71-
.setUnit("By")
72-
.setDescription("The size of HTTP request messages")
73-
.ofLongs()
74-
.build();
75-
responseSize =
76-
meter
77-
.histogramBuilder("http.server.response.size")
78-
.setUnit("By")
79-
.setDescription("The size of HTTP response messages")
80-
.ofLongs()
81-
.build();
8254
}
8355

8456
@Override
8557
public Context onStart(Context context, Attributes startAttributes, long startNanos) {
86-
activeRequests.add(1, applyActiveRequestsView(startAttributes), context);
87-
8858
return context.with(
89-
HTTP_SERVER_REQUEST_METRICS_STATE,
59+
HTTP_SERVER_METRICS_STATE,
9060
new AutoValue_HttpServerMetrics_State(startAttributes, startNanos));
9161
}
9262

9363
@Override
9464
public void onEnd(Context context, Attributes endAttributes, long endNanos) {
95-
State state = context.get(HTTP_SERVER_REQUEST_METRICS_STATE);
65+
State state = context.get(HTTP_SERVER_METRICS_STATE);
9666
if (state == null) {
9767
logger.log(
9868
FINE,
9969
"No state present when ending context {0}. Cannot record HTTP request metrics.",
10070
context);
10171
return;
10272
}
103-
// it's important to use exactly the same attributes that were used when incrementing the active
104-
// request count (otherwise it will split the timeseries)
105-
activeRequests.add(-1, applyActiveRequestsView(state.startAttributes()), context);
106-
10773
Attributes durationAndSizeAttributes =
10874
applyServerDurationAndSizeView(state.startAttributes(), endAttributes);
10975
duration.record(
11076
nanosToUnit(endNanos - state.startTimeNanos()), durationAndSizeAttributes, context);
111-
112-
Long requestBodySize = getHttpRequestBodySize(endAttributes, state.startAttributes());
113-
if (requestBodySize != null) {
114-
requestSize.record(requestBodySize, durationAndSizeAttributes, context);
115-
}
116-
117-
Long responseBodySize = getHttpResponseBodySize(endAttributes, state.startAttributes());
118-
if (responseBodySize != null) {
119-
responseSize.record(responseBodySize, durationAndSizeAttributes, context);
120-
}
12177
}
12278

12379
@AutoValue

0 commit comments

Comments
 (0)