Use attributes advice for HTTP & RPC metrics (#9440)

This commit is contained in:
Mateusz Rzeszutek 2023-09-13 19:27:32 +02:00 committed by GitHub
parent d157b68efb
commit bbbc8dc8e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 320 additions and 895 deletions

View File

@ -7,11 +7,11 @@ package io.opentelemetry.instrumentation.api.instrumenter.http;
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;
@ -49,20 +49,22 @@ public final class HttpClientExperimentalMetrics implements OperationListener {
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
@ -81,7 +83,7 @@ public final class HttpClientExperimentalMetrics implements OperationListener {
return;
}
Attributes sizeAttributes = applyClientRequestSizeView(startAttributes, endAttributes);
Attributes sizeAttributes = startAttributes.toBuilder().putAll(endAttributes).build();
Long requestBodySize = getHttpRequestBodySize(endAttributes, startAttributes);
if (requestBodySize != null) {

View File

@ -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;
@ -52,19 +51,22 @@ public final class HttpClientMetrics implements OperationListener {
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;
}
@ -88,18 +90,14 @@ public final class HttpClientMetrics implements OperationListener {
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);
}
}

View File

@ -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() {}
}

View File

@ -8,7 +8,6 @@ package io.opentelemetry.instrumentation.api.instrumenter.http;
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;
@ -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);
@ -31,7 +30,7 @@ final class HttpMetricsUtil {
((ExtendedDoubleHistogramBuilder) durationBuilder)
.setAdvice(advice -> advice.setExplicitBucketBoundaries(DURATION_SECONDS_BUCKETS));
}
return durationBuilder.build();
return durationBuilder;
}
private HttpMetricsUtil() {}

View File

@ -7,13 +7,13 @@ package io.opentelemetry.instrumentation.api.instrumenter.http;
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;
@ -54,31 +54,34 @@ public final class HttpServerExperimentalMetrics implements OperationListener {
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);
}
@ -95,9 +98,9 @@ public final class HttpServerExperimentalMetrics implements OperationListener {
}
// 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) {

View File

@ -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.applyOldServerDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyStableServerDurationView;
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;
@ -52,19 +51,22 @@ public final class HttpServerMetrics implements OperationListener {
private HttpServerMetrics(Meter meter) {
if (SemconvStability.emitStableHttpSemconv()) {
stableDuration =
createStableDurationHistogram(
DoubleHistogramBuilder stableDurationBuilder =
createStableDurationHistogramBuilder(
meter, "http.server.request.duration", "The duration of the inbound HTTP request");
HttpMetricsAdvice.applyStableServerDurationAdvice(stableDurationBuilder);
stableDuration = stableDurationBuilder.build();
} else {
stableDuration = null;
}
if (SemconvStability.emitOldHttpSemconv()) {
oldDuration =
DoubleHistogramBuilder oldDurationBuilder =
meter
.histogramBuilder("http.server.duration")
.setUnit("ms")
.setDescription("The duration of the inbound HTTP request")
.build();
.setDescription("The duration of the inbound HTTP request");
HttpMetricsAdvice.applyOldServerDurationAdvice(oldDurationBuilder);
oldDuration = oldDurationBuilder.build();
} else {
oldDuration = null;
}
@ -88,18 +90,14 @@ public final class HttpServerMetrics implements OperationListener {
return;
}
Attributes attributes = state.startAttributes().toBuilder().putAll(endAttributes).build();
if (stableDuration != null) {
Attributes stableDurationAttributes =
applyStableServerDurationView(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 =
applyOldServerDurationView(state.startAttributes(), endAttributes);
oldDuration.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_MS, stableDurationAttributes, context);
oldDuration.record((endNanos - state.startTimeNanos()) / NANOS_PER_MS, attributes, context);
}
}

View File

@ -1,168 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.http;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
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;
import java.util.HashSet;
import java.util.Set;
import java.util.function.BiConsumer;
// this is temporary, see
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/3962#issuecomment-906606325
@SuppressWarnings("rawtypes")
final class TemporaryMetricsView {
private static final Set<AttributeKey> stableDurationClientView = buildStableDurationClientView();
private static final Set<AttributeKey> stableDurationServerView = buildStableDurationServerView();
private static final Set<AttributeKey> oldDurationClientView = buildOldDurationClientView();
private static final Set<AttributeKey> oldDurationServerView = buildOldDurationServerView();
private static final Set<AttributeKey> activeRequestsView = buildActiveRequestsView();
private static Set<AttributeKey> buildStableDurationClientView() {
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpclientrequestduration
Set<AttributeKey> view = new HashSet<>();
view.add(HttpAttributes.HTTP_REQUEST_METHOD);
view.add(HttpAttributes.HTTP_RESPONSE_STATUS_CODE);
view.add(NetworkAttributes.NETWORK_PROTOCOL_NAME);
view.add(NetworkAttributes.NETWORK_PROTOCOL_VERSION);
view.add(NetworkAttributes.SERVER_ADDRESS);
view.add(NetworkAttributes.SERVER_PORT);
view.add(NetworkAttributes.SERVER_SOCKET_ADDRESS);
return view;
}
private static Set<AttributeKey> buildOldDurationClientView() {
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpclientduration
Set<AttributeKey> view = new HashSet<>();
view.add(SemanticAttributes.HTTP_METHOD);
view.add(SemanticAttributes.HTTP_STATUS_CODE);
view.add(SemanticAttributes.NET_PEER_NAME);
view.add(SemanticAttributes.NET_PEER_PORT);
view.add(SemanticAttributes.NET_PROTOCOL_NAME);
view.add(SemanticAttributes.NET_PROTOCOL_VERSION);
view.add(SemanticAttributes.NET_SOCK_PEER_ADDR);
return view;
}
private static Set<AttributeKey> buildStableDurationServerView() {
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserverrequestduration
Set<AttributeKey> view = new HashSet<>();
view.add(SemanticAttributes.HTTP_ROUTE);
view.add(HttpAttributes.HTTP_REQUEST_METHOD);
view.add(HttpAttributes.HTTP_RESPONSE_STATUS_CODE);
view.add(NetworkAttributes.NETWORK_PROTOCOL_NAME);
view.add(NetworkAttributes.NETWORK_PROTOCOL_VERSION);
view.add(UrlAttributes.URL_SCHEME);
return view;
}
private static Set<AttributeKey> buildOldDurationServerView() {
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpserverduration
Set<AttributeKey> view = new HashSet<>();
view.add(SemanticAttributes.HTTP_SCHEME);
view.add(SemanticAttributes.HTTP_ROUTE);
view.add(SemanticAttributes.HTTP_METHOD);
view.add(SemanticAttributes.HTTP_STATUS_CODE);
view.add(SemanticAttributes.NET_HOST_NAME);
view.add(SemanticAttributes.NET_HOST_PORT);
view.add(SemanticAttributes.NET_PROTOCOL_NAME);
view.add(SemanticAttributes.NET_PROTOCOL_VERSION);
return view;
}
private static Set<AttributeKey> buildActiveRequestsView() {
Set<AttributeKey> view = new HashSet<>();
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpserveractive_requests
view.add(SemanticAttributes.HTTP_METHOD);
view.add(SemanticAttributes.HTTP_SCHEME);
view.add(SemanticAttributes.NET_HOST_NAME);
view.add(SemanticAttributes.NET_HOST_PORT);
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-metrics.md#metric-httpserveractive_requests
view.add(HttpAttributes.HTTP_REQUEST_METHOD);
view.add(UrlAttributes.URL_SCHEME);
return view;
}
static Attributes applyStableClientDurationView(
Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, stableDurationClientView);
applyView(filtered, endAttributes, stableDurationClientView);
return filtered.build();
}
static Attributes applyOldClientDurationView(
Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, oldDurationClientView);
applyView(filtered, endAttributes, oldDurationClientView);
return filtered.build();
}
static Attributes applyStableServerDurationView(
Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, stableDurationServerView);
applyView(filtered, endAttributes, stableDurationServerView);
return filtered.build();
}
static Attributes applyOldServerDurationView(
Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, oldDurationServerView);
applyView(filtered, endAttributes, oldDurationServerView);
return filtered.build();
}
static Attributes applyServerRequestSizeView(
Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, stableDurationServerView);
applyView(filtered, startAttributes, oldDurationServerView);
applyView(filtered, endAttributes, stableDurationServerView);
applyView(filtered, endAttributes, oldDurationServerView);
return filtered.build();
}
static Attributes applyClientRequestSizeView(
Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, stableDurationClientView);
applyView(filtered, startAttributes, oldDurationClientView);
applyView(filtered, endAttributes, stableDurationClientView);
applyView(filtered, endAttributes, oldDurationClientView);
return filtered.build();
}
static Attributes applyActiveRequestsView(Attributes attributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, attributes, activeRequestsView);
return filtered.build();
}
@SuppressWarnings("unchecked")
private static void applyView(
AttributesBuilder filtered, Attributes attributes, Set<AttributeKey> view) {
attributes.forEach(
(BiConsumer<AttributeKey, Object>)
(key, value) -> {
if (view.contains(key)) {
filtered.put(key, value);
}
});
}
private TemporaryMetricsView() {}
}

View File

@ -1,119 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.rpc;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.HashSet;
import java.util.Set;
import java.util.function.BiConsumer;
// this is temporary, see
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/3962#issuecomment-906606325
@SuppressWarnings("rawtypes")
final class MetricsView {
private static final Set<AttributeKey> alwaysInclude = buildAlwaysInclude();
private static final Set<AttributeKey> clientView = buildClientView();
private static final Set<AttributeKey> serverView = buildServerView();
private static final Set<AttributeKey> serverFallbackView = buildServerFallbackView();
private static Set<AttributeKey> buildAlwaysInclude() {
// the list of recommended metrics attributes is from
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/rpc.md#attributes
Set<AttributeKey> view = new HashSet<>();
view.add(SemanticAttributes.RPC_SYSTEM);
view.add(SemanticAttributes.RPC_SERVICE);
view.add(SemanticAttributes.RPC_METHOD);
view.add(SemanticAttributes.RPC_GRPC_STATUS_CODE);
// stable http semconv
view.add(NetworkAttributes.NETWORK_TYPE);
view.add(NetworkAttributes.NETWORK_TRANSPORT);
view.add(NetworkAttributes.SERVER_ADDRESS);
view.add(NetworkAttributes.SERVER_PORT);
view.add(NetworkAttributes.SERVER_SOCKET_ADDRESS);
view.add(NetworkAttributes.SERVER_SOCKET_PORT);
return view;
}
private static Set<AttributeKey> buildClientView() {
// the list of rpc client metrics attributes is from
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/rpc.md#attributes
Set<AttributeKey> view = new HashSet<>(alwaysInclude);
if (SemconvStability.emitOldHttpSemconv()) {
view.add(SemanticAttributes.NET_PEER_NAME);
view.add(SemanticAttributes.NET_PEER_PORT);
view.add(SemanticAttributes.NET_TRANSPORT);
}
return view;
}
private static Set<AttributeKey> buildServerView() {
// the list of rpc server metrics attributes is from
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/rpc.md#attributes
Set<AttributeKey> view = new HashSet<>(alwaysInclude);
if (SemconvStability.emitOldHttpSemconv()) {
view.add(SemanticAttributes.NET_HOST_NAME);
view.add(SemanticAttributes.NET_TRANSPORT);
}
return view;
}
private static Set<AttributeKey> buildServerFallbackView() {
// the list of rpc server metrics attributes is from
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/rpc.md#attributes
Set<AttributeKey> view = new HashSet<>(alwaysInclude);
if (SemconvStability.emitOldHttpSemconv()) {
view.add(SemanticAttributes.NET_SOCK_HOST_ADDR);
view.add(SemanticAttributes.NET_TRANSPORT);
}
return view;
}
private static <T> boolean containsAttribute(
AttributeKey<T> key, Attributes startAttributes, Attributes endAttributes) {
return startAttributes.get(key) != null || endAttributes.get(key) != null;
}
static Attributes applyClientView(Attributes startAttributes, Attributes endAttributes) {
return applyView(clientView, startAttributes, endAttributes);
}
static Attributes applyServerView(Attributes startAttributes, Attributes endAttributes) {
Set<AttributeKey> fullSet = serverView;
if (SemconvStability.emitOldHttpSemconv()
&& !containsAttribute(SemanticAttributes.NET_HOST_NAME, startAttributes, endAttributes)) {
fullSet = serverFallbackView;
}
return applyView(fullSet, startAttributes, endAttributes);
}
static Attributes applyView(
Set<AttributeKey> view, Attributes startAttributes, Attributes endAttributes) {
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, view);
applyView(filtered, endAttributes, view);
return filtered.build();
}
@SuppressWarnings("unchecked")
private static void applyView(
AttributesBuilder filtered, Attributes attributes, Set<AttributeKey> view) {
attributes.forEach(
(BiConsumer<AttributeKey, Object>)
(key, value) -> {
if (view.contains(key)) {
filtered.put(key, value);
}
});
}
private MetricsView() {}
}

View File

@ -5,12 +5,12 @@
package io.opentelemetry.instrumentation.api.instrumenter.rpc;
import static io.opentelemetry.instrumentation.api.instrumenter.rpc.MetricsView.applyClientView;
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;
@ -36,12 +36,13 @@ public final class RpcClientMetrics implements OperationListener {
private final DoubleHistogram clientDurationHistogram;
private RpcClientMetrics(Meter meter) {
clientDurationHistogram =
DoubleHistogramBuilder durationBuilder =
meter
.histogramBuilder("rpc.client.duration")
.setDescription("The duration of an outbound RPC invocation")
.setUnit("ms")
.build();
.setUnit("ms");
RpcMetricsAdvice.applyClientDurationAdvice(durationBuilder);
clientDurationHistogram = durationBuilder.build();
}
/**
@ -72,7 +73,7 @@ public final class RpcClientMetrics implements OperationListener {
}
clientDurationHistogram.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_MS,
applyClientView(state.startAttributes(), endAttributes),
state.startAttributes().toBuilder().putAll(endAttributes).build(),
context);
}

View File

@ -0,0 +1,82 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.rpc;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.util.ArrayList;
import java.util.List;
final class RpcMetricsAdvice {
static void applyClientDurationAdvice(DoubleHistogramBuilder builder) {
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
return;
}
// the list of recommended metrics attributes is from
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/rpc/rpc-metrics.md
// and
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/rpc-metrics.md
List<AttributeKey<?>> attributes = new ArrayList<>();
attributes.add(SemanticAttributes.RPC_SYSTEM);
attributes.add(SemanticAttributes.RPC_SERVICE);
attributes.add(SemanticAttributes.RPC_METHOD);
attributes.add(SemanticAttributes.RPC_GRPC_STATUS_CODE);
if (SemconvStability.emitStableHttpSemconv()) {
attributes.add(NetworkAttributes.NETWORK_TYPE);
attributes.add(NetworkAttributes.NETWORK_TRANSPORT);
attributes.add(NetworkAttributes.SERVER_ADDRESS);
attributes.add(NetworkAttributes.SERVER_PORT);
attributes.add(NetworkAttributes.SERVER_SOCKET_ADDRESS);
attributes.add(NetworkAttributes.SERVER_SOCKET_PORT);
}
if (SemconvStability.emitOldHttpSemconv()) {
attributes.add(SemanticAttributes.NET_PEER_NAME);
attributes.add(SemanticAttributes.NET_PEER_PORT);
attributes.add(SemanticAttributes.NET_TRANSPORT);
}
((ExtendedDoubleHistogramBuilder) builder)
.setAdvice(advice -> advice.setAttributes(attributes));
}
static void applyServerDurationAdvice(DoubleHistogramBuilder builder) {
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
return;
}
// the list of recommended metrics attributes is from
// https://github.com/open-telemetry/semantic-conventions/blob/main/docs/rpc/rpc-metrics.md
// and
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/rpc-metrics.md
List<AttributeKey<?>> attributes = new ArrayList<>();
attributes.add(SemanticAttributes.RPC_SYSTEM);
attributes.add(SemanticAttributes.RPC_SERVICE);
attributes.add(SemanticAttributes.RPC_METHOD);
attributes.add(SemanticAttributes.RPC_GRPC_STATUS_CODE);
if (SemconvStability.emitStableHttpSemconv()) {
attributes.add(NetworkAttributes.NETWORK_TYPE);
attributes.add(NetworkAttributes.NETWORK_TRANSPORT);
attributes.add(NetworkAttributes.SERVER_ADDRESS);
attributes.add(NetworkAttributes.SERVER_PORT);
attributes.add(NetworkAttributes.SERVER_SOCKET_ADDRESS);
attributes.add(NetworkAttributes.SERVER_SOCKET_PORT);
}
if (SemconvStability.emitOldHttpSemconv()) {
attributes.add(SemanticAttributes.NET_HOST_NAME);
attributes.add(SemanticAttributes.NET_SOCK_HOST_ADDR);
attributes.add(SemanticAttributes.NET_TRANSPORT);
}
((ExtendedDoubleHistogramBuilder) builder)
.setAdvice(advice -> advice.setAttributes(attributes));
}
private RpcMetricsAdvice() {}
}

View File

@ -5,12 +5,12 @@
package io.opentelemetry.instrumentation.api.instrumenter.rpc;
import static io.opentelemetry.instrumentation.api.instrumenter.rpc.MetricsView.applyServerView;
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;
@ -36,12 +36,13 @@ public final class RpcServerMetrics implements OperationListener {
private final DoubleHistogram serverDurationHistogram;
private RpcServerMetrics(Meter meter) {
serverDurationHistogram =
DoubleHistogramBuilder durationBuilder =
meter
.histogramBuilder("rpc.server.duration")
.setDescription("The duration of an inbound RPC invocation")
.setUnit("ms")
.build();
.setUnit("ms");
RpcMetricsAdvice.applyServerDurationAdvice(durationBuilder);
serverDurationHistogram = durationBuilder.build();
}
/**
@ -72,7 +73,7 @@ public final class RpcServerMetrics implements OperationListener {
}
serverDurationHistogram.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_MS,
applyServerView(state.startAttributes(), endAttributes),
state.startAttributes().toBuilder().putAll(endAttributes).build(),
context);
}

View File

@ -1,397 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.http;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyActiveRequestsView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyClientRequestSizeView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyOldClientDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyOldServerDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyServerRequestSizeView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyStableClientDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyStableServerDurationView;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP;
import static org.assertj.core.api.Assertions.entry;
import io.opentelemetry.api.common.Attributes;
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;
import org.junit.jupiter.api.Test;
class TemporaryMetricsViewTest {
@Test
void shouldApplyClientDurationView() {
Attributes startAttributes =
Attributes.builder()
.put(
SemanticAttributes.HTTP_URL,
"https://somehost/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_METHOD, "GET")
.put(SemanticAttributes.HTTP_SCHEME, "https")
.put(SemanticAttributes.HTTP_TARGET, "/high/cardinality/12345?jsessionId=121454")
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_STATUS_CODE, 500)
.put(SemanticAttributes.NET_TRANSPORT, IP_TCP)
.put(SemanticAttributes.NET_PROTOCOL_NAME, "http")
.put(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1")
.put(SemanticAttributes.NET_PEER_NAME, "somehost2")
.put(SemanticAttributes.NET_PEER_PORT, 443)
.put(SemanticAttributes.NET_SOCK_FAMILY, "inet")
.put(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4")
.put(SemanticAttributes.NET_SOCK_PEER_NAME, "somehost20")
.put(SemanticAttributes.NET_SOCK_PEER_PORT, 8080)
.build();
assertThat(applyOldClientDurationView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.HTTP_METHOD, "GET"),
entry(SemanticAttributes.HTTP_STATUS_CODE, 500L),
entry(SemanticAttributes.NET_PROTOCOL_NAME, "http"),
entry(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1"),
entry(SemanticAttributes.NET_PEER_NAME, "somehost2"),
entry(SemanticAttributes.NET_PEER_PORT, 443L),
entry(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4"));
}
@Test
void shouldApplyClientDurationView_stableSemconv() {
Attributes startAttributes =
Attributes.builder()
.put(
UrlAttributes.URL_FULL, "https://somehost/high/cardinality/12345?jsessionId=121454")
.put(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
.put(UrlAttributes.URL_SCHEME, "https")
.put(UrlAttributes.URL_PATH, "/high/cardinality/12345")
.put(UrlAttributes.URL_QUERY, "jsessionId=121454")
.put(NetworkAttributes.SERVER_ADDRESS, "somehost2")
.put(NetworkAttributes.SERVER_PORT, 443)
.build();
Attributes endAttributes =
Attributes.builder()
.put(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500)
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http")
.put(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1")
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "1.2.3.4")
.put(NetworkAttributes.SERVER_SOCKET_DOMAIN, "somehost20")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 8080)
.build();
assertThat(applyStableClientDurationView(startAttributes, endAttributes))
.containsOnly(
entry(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
entry(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500L),
entry(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http"),
entry(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
entry(NetworkAttributes.SERVER_ADDRESS, "somehost2"),
entry(NetworkAttributes.SERVER_PORT, 443L),
entry(NetworkAttributes.SERVER_SOCKET_ADDRESS, "1.2.3.4"));
}
@Test
void shouldApplyServerDurationView() {
Attributes startAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_METHOD, "GET")
.put(
SemanticAttributes.HTTP_URL,
"https://somehost/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_TARGET, "/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_SCHEME, "https")
.put(SemanticAttributes.NET_TRANSPORT, IP_TCP)
.put(SemanticAttributes.NET_PROTOCOL_NAME, "http")
.put(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1")
.put(SemanticAttributes.NET_HOST_NAME, "somehost")
.put(SemanticAttributes.NET_HOST_PORT, 443)
.put(SemanticAttributes.NET_SOCK_FAMILY, "inet")
.put(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4")
.put(SemanticAttributes.NET_SOCK_PEER_PORT, 8080)
.put(SemanticAttributes.NET_SOCK_HOST_ADDR, "4.3.2.1")
.put(SemanticAttributes.NET_SOCK_HOST_PORT, 9090)
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}")
.put(SemanticAttributes.HTTP_STATUS_CODE, 500)
.put(SemanticAttributes.NET_PEER_NAME, "somehost2")
.put(SemanticAttributes.NET_PEER_PORT, 443)
.build();
assertThat(applyOldServerDurationView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.HTTP_METHOD, "GET"),
entry(SemanticAttributes.HTTP_STATUS_CODE, 500L),
entry(SemanticAttributes.HTTP_SCHEME, "https"),
entry(SemanticAttributes.NET_PROTOCOL_NAME, "http"),
entry(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1"),
entry(SemanticAttributes.NET_HOST_NAME, "somehost"),
entry(SemanticAttributes.NET_HOST_PORT, 443L),
entry(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}"));
}
@Test
void shouldApplyServerDurationView_stableSemconv() {
Attributes startAttributes =
Attributes.builder()
.put(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
.put(
UrlAttributes.URL_FULL, "https://somehost/high/cardinality/12345?jsessionId=121454")
.put(UrlAttributes.URL_SCHEME, "https")
.put(UrlAttributes.URL_PATH, "/high/cardinality/12345")
.put(UrlAttributes.URL_QUERY, "jsessionId=121454")
.put(NetworkAttributes.SERVER_ADDRESS, "somehost")
.put(NetworkAttributes.SERVER_PORT, 443)
.put(NetworkAttributes.CLIENT_ADDRESS, "somehost2")
.put(NetworkAttributes.CLIENT_PORT, 443)
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}")
.put(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500)
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http")
.put(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1")
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "4.3.2.1")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 9090)
.put(NetworkAttributes.CLIENT_SOCKET_ADDRESS, "1.2.3.4")
.put(NetworkAttributes.CLIENT_SOCKET_PORT, 8080)
.build();
assertThat(applyStableServerDurationView(startAttributes, endAttributes))
.containsOnly(
entry(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
entry(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500L),
entry(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}"),
entry(UrlAttributes.URL_SCHEME, "https"),
entry(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http"),
entry(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"));
}
@Test
void shouldApplyClientSizeView() {
Attributes startAttributes =
Attributes.builder()
.put(
SemanticAttributes.HTTP_URL,
"https://somehost/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_METHOD, "GET")
.put(SemanticAttributes.HTTP_SCHEME, "https")
.put(SemanticAttributes.HTTP_TARGET, "/high/cardinality/12345?jsessionId=121454")
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_STATUS_CODE, 500)
.put(SemanticAttributes.NET_TRANSPORT, IP_TCP)
.put(SemanticAttributes.NET_PROTOCOL_NAME, "http")
.put(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1")
.put(SemanticAttributes.NET_PEER_NAME, "somehost2")
.put(SemanticAttributes.NET_PEER_PORT, 443)
.put(SemanticAttributes.NET_SOCK_FAMILY, "inet")
.put(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4")
.put(SemanticAttributes.NET_SOCK_PEER_NAME, "somehost20")
.put(SemanticAttributes.NET_SOCK_PEER_PORT, 8080)
.build();
assertThat(applyClientRequestSizeView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.HTTP_METHOD, "GET"),
entry(SemanticAttributes.HTTP_STATUS_CODE, 500L),
entry(SemanticAttributes.NET_PROTOCOL_NAME, "http"),
entry(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1"),
entry(SemanticAttributes.NET_PEER_NAME, "somehost2"),
entry(SemanticAttributes.NET_PEER_PORT, 443L),
entry(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4"));
}
@Test
void shouldApplyClientSizeView_stableSemconv() {
Attributes startAttributes =
Attributes.builder()
.put(
UrlAttributes.URL_FULL, "https://somehost/high/cardinality/12345?jsessionId=121454")
.put(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
.put(UrlAttributes.URL_SCHEME, "https")
.put(UrlAttributes.URL_PATH, "/high/cardinality/12345")
.put(UrlAttributes.URL_QUERY, "jsessionId=121454")
.put(NetworkAttributes.SERVER_ADDRESS, "somehost2")
.put(NetworkAttributes.SERVER_PORT, 443)
.build();
Attributes endAttributes =
Attributes.builder()
.put(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500)
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http")
.put(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1")
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "1.2.3.4")
.put(NetworkAttributes.SERVER_SOCKET_DOMAIN, "somehost20")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 8080)
.build();
assertThat(applyClientRequestSizeView(startAttributes, endAttributes))
.containsOnly(
entry(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
entry(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500L),
entry(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http"),
entry(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"),
entry(NetworkAttributes.SERVER_ADDRESS, "somehost2"),
entry(NetworkAttributes.SERVER_PORT, 443L),
entry(NetworkAttributes.SERVER_SOCKET_ADDRESS, "1.2.3.4"));
}
@Test
void shouldApplyServerSizeView() {
Attributes startAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_METHOD, "GET")
.put(
SemanticAttributes.HTTP_URL,
"https://somehost/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_TARGET, "/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_SCHEME, "https")
.put(SemanticAttributes.NET_TRANSPORT, IP_TCP)
.put(SemanticAttributes.NET_PROTOCOL_NAME, "http")
.put(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1")
.put(SemanticAttributes.NET_HOST_NAME, "somehost")
.put(SemanticAttributes.NET_HOST_PORT, 443)
.put(SemanticAttributes.NET_SOCK_FAMILY, "inet")
.put(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4")
.put(SemanticAttributes.NET_SOCK_PEER_PORT, 8080)
.put(SemanticAttributes.NET_SOCK_HOST_ADDR, "4.3.2.1")
.put(SemanticAttributes.NET_SOCK_HOST_PORT, 9090)
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}")
.put(SemanticAttributes.HTTP_STATUS_CODE, 500)
.put(SemanticAttributes.NET_PEER_NAME, "somehost2")
.put(SemanticAttributes.NET_PEER_PORT, 443)
.build();
assertThat(applyServerRequestSizeView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.HTTP_METHOD, "GET"),
entry(SemanticAttributes.HTTP_STATUS_CODE, 500L),
entry(SemanticAttributes.HTTP_SCHEME, "https"),
entry(SemanticAttributes.NET_PROTOCOL_NAME, "http"),
entry(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1"),
entry(SemanticAttributes.NET_HOST_NAME, "somehost"),
entry(SemanticAttributes.NET_HOST_PORT, 443L),
entry(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}"));
}
@Test
void shouldApplyServerSizeView_stableSemconv() {
Attributes startAttributes =
Attributes.builder()
.put(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
.put(
UrlAttributes.URL_FULL, "https://somehost/high/cardinality/12345?jsessionId=121454")
.put(UrlAttributes.URL_SCHEME, "https")
.put(UrlAttributes.URL_PATH, "/high/cardinality/12345")
.put(UrlAttributes.URL_QUERY, "jsessionId=121454")
.put(NetworkAttributes.SERVER_ADDRESS, "somehost")
.put(NetworkAttributes.SERVER_PORT, 443)
.put(NetworkAttributes.CLIENT_ADDRESS, "somehost2")
.put(NetworkAttributes.CLIENT_PORT, 443)
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}")
.put(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500)
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http")
.put(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1")
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "4.3.2.1")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 9090)
.put(NetworkAttributes.CLIENT_SOCKET_ADDRESS, "1.2.3.4")
.put(NetworkAttributes.CLIENT_SOCKET_PORT, 8080)
.build();
assertThat(applyServerRequestSizeView(startAttributes, endAttributes))
.containsOnly(
entry(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
entry(HttpAttributes.HTTP_RESPONSE_STATUS_CODE, 500L),
entry(SemanticAttributes.HTTP_ROUTE, "/somehost/high/{name}/{id}"),
entry(UrlAttributes.URL_SCHEME, "https"),
entry(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http"),
entry(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1"));
}
@Test
void shouldApplyActiveRequestsView() {
Attributes attributes =
Attributes.builder()
.put(SemanticAttributes.HTTP_METHOD, "GET")
.put(
SemanticAttributes.HTTP_URL,
"https://somehost/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_TARGET, "/high/cardinality/12345?jsessionId=121454")
.put(SemanticAttributes.HTTP_SCHEME, "https")
.put(SemanticAttributes.NET_TRANSPORT, IP_TCP)
.put(SemanticAttributes.NET_PROTOCOL_NAME, "http")
.put(SemanticAttributes.NET_PROTOCOL_VERSION, "1.1")
.put(SemanticAttributes.NET_HOST_NAME, "somehost")
.put(SemanticAttributes.NET_HOST_PORT, 443)
.put(SemanticAttributes.NET_SOCK_FAMILY, "inet")
.put(SemanticAttributes.NET_SOCK_PEER_ADDR, "1.2.3.4")
.put(SemanticAttributes.NET_SOCK_PEER_PORT, 8080)
.put(SemanticAttributes.NET_SOCK_HOST_ADDR, "4.3.2.1")
.put(SemanticAttributes.NET_SOCK_HOST_PORT, 9090)
.build();
assertThat(applyActiveRequestsView(attributes))
.containsOnly(
entry(SemanticAttributes.HTTP_METHOD, "GET"),
entry(SemanticAttributes.HTTP_SCHEME, "https"),
entry(SemanticAttributes.NET_HOST_NAME, "somehost"),
entry(SemanticAttributes.NET_HOST_PORT, 443L));
}
@Test
void shouldApplyActiveRequestsView_stableSemconv() {
Attributes attributes =
Attributes.builder()
.put(HttpAttributes.HTTP_REQUEST_METHOD, "GET")
.put(
UrlAttributes.URL_FULL, "https://somehost/high/cardinality/12345?jsessionId=121454")
.put(UrlAttributes.URL_SCHEME, "https")
.put(UrlAttributes.URL_PATH, "/high/cardinality/12345")
.put(UrlAttributes.URL_QUERY, "jsessionId=121454")
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_PROTOCOL_NAME, "http")
.put(NetworkAttributes.NETWORK_PROTOCOL_VERSION, "1.1")
.put(NetworkAttributes.SERVER_ADDRESS, "somehost")
.put(NetworkAttributes.SERVER_PORT, 443)
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "4.3.2.1")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 9090)
.put(NetworkAttributes.CLIENT_SOCKET_ADDRESS, "1.2.3.4")
.put(NetworkAttributes.CLIENT_SOCKET_PORT, 8080)
.build();
assertThat(applyActiveRequestsView(attributes))
.containsOnly(
entry(HttpAttributes.HTTP_REQUEST_METHOD, "GET"),
entry(UrlAttributes.URL_SCHEME, "https"));
}
}

View File

@ -1,144 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.api.instrumenter.rpc;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.instrumentation.api.instrumenter.rpc.MetricsView.applyClientView;
import static io.opentelemetry.instrumentation.api.instrumenter.rpc.MetricsView.applyServerView;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.instrumentation.api.instrumenter.network.internal.NetworkAttributes;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import org.junit.jupiter.api.Test;
class MetricsViewTest {
@Test
void shouldApplyClientView() {
Attributes startAttributes =
Attributes.builder()
.put(SemanticAttributes.RPC_SYSTEM, "grpc")
.put(SemanticAttributes.RPC_SERVICE, "myservice.EchoService")
.put(SemanticAttributes.RPC_METHOD, "exampleMethod")
.put(stringKey("one"), "1")
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.NET_PEER_NAME, "example.com")
.put(SemanticAttributes.NET_PEER_PORT, 8080)
.put(SemanticAttributes.NET_TRANSPORT, "ip_tcp")
.put(stringKey("two"), "2")
.build();
assertThat(applyClientView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.RPC_SYSTEM, "grpc"),
entry(SemanticAttributes.RPC_SERVICE, "myservice.EchoService"),
entry(SemanticAttributes.RPC_METHOD, "exampleMethod"),
entry(SemanticAttributes.NET_PEER_NAME, "example.com"),
entry(SemanticAttributes.NET_PEER_PORT, 8080L),
entry(SemanticAttributes.NET_TRANSPORT, "ip_tcp"));
}
@Test
void shouldApplyClientView_stableHttpSemconv() {
Attributes startAttributes =
Attributes.builder()
.put(SemanticAttributes.RPC_SYSTEM, "grpc")
.put(SemanticAttributes.RPC_SERVICE, "myservice.EchoService")
.put(SemanticAttributes.RPC_METHOD, "exampleMethod")
.put(stringKey("one"), "1")
.build();
Attributes endAttributes =
Attributes.builder()
.put(NetworkAttributes.SERVER_ADDRESS, "example.com")
.put(NetworkAttributes.SERVER_PORT, 8080)
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "127.0.0.1")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 12345)
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(stringKey("two"), "2")
.build();
assertThat(applyClientView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.RPC_SYSTEM, "grpc"),
entry(SemanticAttributes.RPC_SERVICE, "myservice.EchoService"),
entry(SemanticAttributes.RPC_METHOD, "exampleMethod"),
entry(NetworkAttributes.SERVER_ADDRESS, "example.com"),
entry(NetworkAttributes.SERVER_PORT, 8080L),
entry(NetworkAttributes.SERVER_SOCKET_ADDRESS, "127.0.0.1"),
entry(NetworkAttributes.SERVER_SOCKET_PORT, 12345L),
entry(NetworkAttributes.NETWORK_TYPE, "ipv4"),
entry(NetworkAttributes.NETWORK_TRANSPORT, "tcp"));
}
@Test
void shouldApplyServerView() {
Attributes startAttributes =
Attributes.builder()
.put(SemanticAttributes.RPC_SYSTEM, "grpc")
.put(SemanticAttributes.RPC_SERVICE, "myservice.EchoService")
.put(SemanticAttributes.RPC_METHOD, "exampleMethod")
.put(stringKey("one"), "1")
.build();
Attributes endAttributes =
Attributes.builder()
.put(SemanticAttributes.NET_HOST_NAME, "example.com")
.put(SemanticAttributes.NET_SOCK_HOST_ADDR, "127.0.0.1")
.put(SemanticAttributes.NET_HOST_PORT, 8080)
.put(SemanticAttributes.NET_TRANSPORT, "ip_tcp")
.put(stringKey("two"), "2")
.build();
assertThat(applyServerView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.RPC_SYSTEM, "grpc"),
entry(SemanticAttributes.RPC_SERVICE, "myservice.EchoService"),
entry(SemanticAttributes.RPC_METHOD, "exampleMethod"),
entry(SemanticAttributes.NET_HOST_NAME, "example.com"),
entry(SemanticAttributes.NET_TRANSPORT, "ip_tcp"));
}
@Test
void shouldApplyServerView_stableHttpSemconv() {
Attributes startAttributes =
Attributes.builder()
.put(SemanticAttributes.RPC_SYSTEM, "grpc")
.put(SemanticAttributes.RPC_SERVICE, "myservice.EchoService")
.put(SemanticAttributes.RPC_METHOD, "exampleMethod")
.put(stringKey("one"), "1")
.build();
Attributes endAttributes =
Attributes.builder()
.put(NetworkAttributes.SERVER_ADDRESS, "example.com")
.put(NetworkAttributes.SERVER_PORT, 8080)
.put(NetworkAttributes.SERVER_SOCKET_ADDRESS, "127.0.0.1")
.put(NetworkAttributes.SERVER_SOCKET_PORT, 12345)
.put(NetworkAttributes.NETWORK_TYPE, "ipv4")
.put(NetworkAttributes.NETWORK_TRANSPORT, "tcp")
.put(stringKey("two"), "2")
.build();
assertThat(applyServerView(startAttributes, endAttributes))
.containsOnly(
entry(SemanticAttributes.RPC_SYSTEM, "grpc"),
entry(SemanticAttributes.RPC_SERVICE, "myservice.EchoService"),
entry(SemanticAttributes.RPC_METHOD, "exampleMethod"),
entry(NetworkAttributes.SERVER_ADDRESS, "example.com"),
entry(NetworkAttributes.SERVER_PORT, 8080L),
entry(NetworkAttributes.SERVER_SOCKET_ADDRESS, "127.0.0.1"),
entry(NetworkAttributes.SERVER_SOCKET_PORT, 12345L),
entry(NetworkAttributes.NETWORK_TYPE, "ipv4"),
entry(NetworkAttributes.NETWORK_TRANSPORT, "tcp"));
}
}