Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use attributes advice for HTTP & RPC metrics #9440

Merged
merged 2 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpRequestBodySize;
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpResponseBodySize;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyClientRequestSizeView;
import static java.util.logging.Level.FINE;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongHistogram;
import io.opentelemetry.api.metrics.LongHistogramBuilder;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ContextKey;
Expand Down Expand Up @@ -49,20 +49,22 @@ public static OperationMetrics get() {
private final LongHistogram responseSize;

private HttpClientExperimentalMetrics(Meter meter) {
requestSize =
LongHistogramBuilder requestSizeBuilder =
meter
.histogramBuilder("http.client.request.size")
.setUnit("By")
.setDescription("The size of HTTP request messages")
.ofLongs()
.build();
responseSize =
.ofLongs();
HttpMetricsAdvice.applyClientRequestSizeAdvice(requestSizeBuilder);
requestSize = requestSizeBuilder.build();
LongHistogramBuilder responseSizeBuilder =
meter
.histogramBuilder("http.client.response.size")
.setUnit("By")
.setDescription("The size of HTTP response messages")
.ofLongs()
.build();
.ofLongs();
HttpMetricsAdvice.applyClientRequestSizeAdvice(responseSizeBuilder);
responseSize = responseSizeBuilder.build();
}

@Override
Expand All @@ -81,7 +83,7 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
return;
}

Attributes sizeAttributes = applyClientRequestSizeView(startAttributes, endAttributes);
Attributes sizeAttributes = startAttributes.toBuilder().putAll(endAttributes).build();

Long requestBodySize = getHttpRequestBodySize(endAttributes, startAttributes);
if (requestBodySize != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

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

import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMetricsUtil.createStableDurationHistogram;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyOldClientDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyStableClientDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMetricsUtil.createStableDurationHistogramBuilder;
import static java.util.logging.Level.FINE;

import com.google.auto.value.AutoValue;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ContextKey;
Expand Down Expand Up @@ -52,19 +51,22 @@ public static OperationMetrics get() {

private HttpClientMetrics(Meter meter) {
if (SemconvStability.emitStableHttpSemconv()) {
stableDuration =
createStableDurationHistogram(
DoubleHistogramBuilder stableDurationBuilder =
createStableDurationHistogramBuilder(
meter, "http.client.request.duration", "The duration of the outbound HTTP request");
HttpMetricsAdvice.applyStableClientDurationAdvice(stableDurationBuilder);
stableDuration = stableDurationBuilder.build();
} else {
stableDuration = null;
}
if (SemconvStability.emitOldHttpSemconv()) {
oldDuration =
DoubleHistogramBuilder oldDurationBuilder =
meter
.histogramBuilder("http.client.duration")
.setUnit("ms")
.setDescription("The duration of the outbound HTTP request")
.build();
.setDescription("The duration of the outbound HTTP request");
HttpMetricsAdvice.applyOldClientDurationAdvice(oldDurationBuilder);
oldDuration = oldDurationBuilder.build();
} else {
oldDuration = null;
}
Expand All @@ -88,18 +90,14 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
return;
}

Attributes attributes = state.startAttributes().toBuilder().putAll(endAttributes).build();

if (stableDuration != null) {
Attributes stableDurationAttributes =
applyStableClientDurationView(state.startAttributes(), endAttributes);
stableDuration.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_S, stableDurationAttributes, context);
stableDuration.record((endNanos - state.startTimeNanos()) / NANOS_PER_S, attributes, context);
}

if (oldDuration != null) {
Attributes stableDurationAttributes =
applyOldClientDurationView(state.startAttributes(), endAttributes);
oldDuration.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_MS, stableDurationAttributes, context);
oldDuration.record((endNanos - state.startTimeNanos()) / NANOS_PER_MS, attributes, context);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

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

import static java.util.Arrays.asList;

import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
import io.opentelemetry.api.metrics.LongHistogramBuilder;
import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder;
import io.opentelemetry.extension.incubator.metrics.ExtendedLongHistogramBuilder;
import io.opentelemetry.extension.incubator.metrics.ExtendedLongUpDownCounterBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.http.internal.HttpAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
import io.opentelemetry.instrumentation.api.instrumenter.url.internal.UrlAttributes;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;

final class HttpMetricsAdvice {

static void applyStableClientDurationAdvice(DoubleHistogramBuilder builder) {
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
return;
}
((ExtendedDoubleHistogramBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
HttpAttributes.HTTP_REQUEST_METHOD,
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
NetworkAttributes.NETWORK_PROTOCOL_NAME,
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
NetworkAttributes.SERVER_ADDRESS,
NetworkAttributes.SERVER_PORT,
NetworkAttributes.SERVER_SOCKET_ADDRESS)));
}

static void applyOldClientDurationAdvice(DoubleHistogramBuilder builder) {
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
return;
}
((ExtendedDoubleHistogramBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
SemanticAttributes.HTTP_METHOD,
SemanticAttributes.HTTP_STATUS_CODE,
SemanticAttributes.NET_PEER_NAME,
SemanticAttributes.NET_PEER_PORT,
SemanticAttributes.NET_PROTOCOL_NAME,
SemanticAttributes.NET_PROTOCOL_VERSION,
SemanticAttributes.NET_SOCK_PEER_ADDR)));
}

static void applyClientRequestSizeAdvice(LongHistogramBuilder builder) {
if (!(builder instanceof ExtendedLongHistogramBuilder)) {
return;
}
((ExtendedLongHistogramBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
// stable attributes
HttpAttributes.HTTP_REQUEST_METHOD,
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
NetworkAttributes.NETWORK_PROTOCOL_NAME,
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
NetworkAttributes.SERVER_ADDRESS,
NetworkAttributes.SERVER_PORT,
NetworkAttributes.SERVER_SOCKET_ADDRESS,
// old attributes
SemanticAttributes.HTTP_METHOD,
SemanticAttributes.HTTP_STATUS_CODE,
SemanticAttributes.NET_PEER_NAME,
SemanticAttributes.NET_PEER_PORT,
SemanticAttributes.NET_PROTOCOL_NAME,
SemanticAttributes.NET_PROTOCOL_VERSION,
SemanticAttributes.NET_SOCK_PEER_ADDR)));
}

static void applyStableServerDurationAdvice(DoubleHistogramBuilder builder) {
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
return;
}
((ExtendedDoubleHistogramBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
SemanticAttributes.HTTP_ROUTE,
HttpAttributes.HTTP_REQUEST_METHOD,
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
NetworkAttributes.NETWORK_PROTOCOL_NAME,
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
UrlAttributes.URL_SCHEME)));
}

static void applyOldServerDurationAdvice(DoubleHistogramBuilder builder) {
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
return;
}
((ExtendedDoubleHistogramBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
SemanticAttributes.HTTP_SCHEME,
SemanticAttributes.HTTP_ROUTE,
SemanticAttributes.HTTP_METHOD,
SemanticAttributes.HTTP_STATUS_CODE,
SemanticAttributes.NET_HOST_NAME,
SemanticAttributes.NET_HOST_PORT,
SemanticAttributes.NET_PROTOCOL_NAME,
SemanticAttributes.NET_PROTOCOL_VERSION)));
}

static void applyServerRequestSizeAdvice(LongHistogramBuilder builder) {
if (!(builder instanceof ExtendedLongHistogramBuilder)) {
return;
}
((ExtendedLongHistogramBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
// stable attributes
SemanticAttributes.HTTP_ROUTE,
HttpAttributes.HTTP_REQUEST_METHOD,
HttpAttributes.HTTP_RESPONSE_STATUS_CODE,
NetworkAttributes.NETWORK_PROTOCOL_NAME,
NetworkAttributes.NETWORK_PROTOCOL_VERSION,
UrlAttributes.URL_SCHEME,
// old attributes
SemanticAttributes.HTTP_SCHEME,
SemanticAttributes.HTTP_ROUTE,
SemanticAttributes.HTTP_METHOD,
SemanticAttributes.HTTP_STATUS_CODE,
SemanticAttributes.NET_HOST_NAME,
SemanticAttributes.NET_HOST_PORT,
SemanticAttributes.NET_PROTOCOL_NAME,
SemanticAttributes.NET_PROTOCOL_VERSION)));
}

static void applyServerActiveRequestsAdvice(LongUpDownCounterBuilder builder) {
if (!(builder instanceof ExtendedLongUpDownCounterBuilder)) {
return;
}
((ExtendedLongUpDownCounterBuilder) builder)
.setAdvice(
advice ->
advice.setAttributes(
asList(
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpserveractive_requests
SemanticAttributes.HTTP_METHOD,
SemanticAttributes.HTTP_SCHEME,
SemanticAttributes.NET_HOST_NAME,
SemanticAttributes.NET_HOST_PORT,
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserveractive_requests
HttpAttributes.HTTP_REQUEST_METHOD,
UrlAttributes.URL_SCHEME)));
}

private HttpMetricsAdvice() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableList;

import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder;
Expand All @@ -22,7 +21,7 @@ final class HttpMetricsUtil {
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,
10.0));

static DoubleHistogram createStableDurationHistogram(
static DoubleHistogramBuilder createStableDurationHistogramBuilder(
Meter meter, String name, String description) {
DoubleHistogramBuilder durationBuilder =
meter.histogramBuilder(name).setUnit("s").setDescription(description);
Expand All @@ -31,7 +30,7 @@ static DoubleHistogram createStableDurationHistogram(
((ExtendedDoubleHistogramBuilder) durationBuilder)
.setAdvice(advice -> advice.setExplicitBucketBoundaries(DURATION_SECONDS_BUCKETS));
}
return durationBuilder.build();
return durationBuilder;
}

private HttpMetricsUtil() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpRequestBodySize;
import static io.opentelemetry.instrumentation.api.instrumenter.http.HttpMessageBodySizeUtil.getHttpResponseBodySize;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyActiveRequestsView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyServerRequestSizeView;
import static java.util.logging.Level.FINE;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongHistogram;
import io.opentelemetry.api.metrics.LongHistogramBuilder;
import io.opentelemetry.api.metrics.LongUpDownCounter;
import io.opentelemetry.api.metrics.LongUpDownCounterBuilder;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.ContextKey;
Expand Down Expand Up @@ -54,31 +54,34 @@ public static OperationMetrics get() {
private final LongHistogram responseSize;

private HttpServerExperimentalMetrics(Meter meter) {
activeRequests =
LongUpDownCounterBuilder activeRequestsBuilder =
meter
.upDownCounterBuilder("http.server.active_requests")
.setUnit("{requests}")
.setDescription("The number of concurrent HTTP requests that are currently in-flight")
.build();
requestSize =
.setDescription("The number of concurrent HTTP requests that are currently in-flight");
HttpMetricsAdvice.applyServerActiveRequestsAdvice(activeRequestsBuilder);
activeRequests = activeRequestsBuilder.build();
LongHistogramBuilder requestSizeBuilder =
meter
.histogramBuilder("http.server.request.size")
.setUnit("By")
.setDescription("The size of HTTP request messages")
.ofLongs()
.build();
responseSize =
.ofLongs();
HttpMetricsAdvice.applyServerRequestSizeAdvice(requestSizeBuilder);
requestSize = requestSizeBuilder.build();
LongHistogramBuilder responseSizeBuilder =
meter
.histogramBuilder("http.server.response.size")
.setUnit("By")
.setDescription("The size of HTTP response messages")
.ofLongs()
.build();
.ofLongs();
HttpMetricsAdvice.applyServerRequestSizeAdvice(responseSizeBuilder);
responseSize = responseSizeBuilder.build();
}

@Override
public Context onStart(Context context, Attributes startAttributes, long startNanos) {
activeRequests.add(1, applyActiveRequestsView(startAttributes), context);
activeRequests.add(1, startAttributes, context);

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

Attributes sizeAttributes = applyServerRequestSizeView(startAttributes, endAttributes);
Attributes sizeAttributes = startAttributes.toBuilder().putAll(endAttributes).build();

Long requestBodySize = getHttpRequestBodySize(endAttributes, startAttributes);
if (requestBodySize != null) {
Expand Down
Loading
Loading