Specify `http.(client|server).duration` buckets using advice API (#8435)
This commit is contained in:
parent
d7d629617a
commit
28cf44cef4
|
@ -13,6 +13,7 @@ group = "io.opentelemetry.instrumentation"
|
|||
dependencies {
|
||||
api("io.opentelemetry:opentelemetry-semconv")
|
||||
api(project(":instrumentation-api"))
|
||||
implementation("io.opentelemetry:opentelemetry-extension-incubator")
|
||||
|
||||
compileOnly("com.google.auto.value:auto-value-annotations")
|
||||
annotationProcessor("com.google.auto.value:auto-value")
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.instrumenter.http;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
||||
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
|
||||
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleHistogramBuilder;
|
||||
import java.util.List;
|
||||
|
||||
final class HistogramAdviceUtil {
|
||||
|
||||
static final List<Double> DURATION_SECONDS_BUCKETS =
|
||||
unmodifiableList(
|
||||
asList(
|
||||
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 void setHttpDurationBuckets(DoubleHistogramBuilder builder) {
|
||||
if (!(builder instanceof ExtendedDoubleHistogramBuilder)) {
|
||||
// that shouldn't really happen
|
||||
return;
|
||||
}
|
||||
((ExtendedDoubleHistogramBuilder) builder)
|
||||
.setAdvice(advice -> advice.setExplicitBucketBoundaries(DURATION_SECONDS_BUCKETS));
|
||||
}
|
||||
|
||||
private HistogramAdviceUtil() {}
|
||||
}
|
|
@ -12,6 +12,7 @@ import com.google.auto.value.AutoValue;
|
|||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogram;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
|
||||
import io.opentelemetry.api.metrics.LongHistogram;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.context.Context;
|
||||
|
@ -30,7 +31,7 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
public final class HttpClientMetrics implements OperationListener {
|
||||
|
||||
private static final double NANOS_PER_MS = TimeUnit.MILLISECONDS.toNanos(1);
|
||||
private static final double NANOS_PER_S = TimeUnit.SECONDS.toNanos(1);
|
||||
|
||||
private static final ContextKey<State> HTTP_CLIENT_REQUEST_METRICS_STATE =
|
||||
ContextKey.named("http-client-request-metrics-state");
|
||||
|
@ -51,12 +52,13 @@ public final class HttpClientMetrics implements OperationListener {
|
|||
private final LongHistogram responseSize;
|
||||
|
||||
private HttpClientMetrics(Meter meter) {
|
||||
duration =
|
||||
DoubleHistogramBuilder durationBuilder =
|
||||
meter
|
||||
.histogramBuilder("http.client.duration")
|
||||
.setUnit("ms")
|
||||
.setDescription("The duration of the outbound HTTP request")
|
||||
.build();
|
||||
.setUnit("s")
|
||||
.setDescription("The duration of the outbound HTTP request");
|
||||
HistogramAdviceUtil.setHttpDurationBuckets(durationBuilder);
|
||||
duration = durationBuilder.build();
|
||||
requestSize =
|
||||
meter
|
||||
.histogramBuilder("http.client.request.size")
|
||||
|
@ -93,7 +95,7 @@ public final class HttpClientMetrics implements OperationListener {
|
|||
Attributes durationAndSizeAttributes =
|
||||
applyClientDurationAndSizeView(state.startAttributes(), endAttributes);
|
||||
duration.record(
|
||||
(endNanos - state.startTimeNanos()) / NANOS_PER_MS, durationAndSizeAttributes, context);
|
||||
(endNanos - state.startTimeNanos()) / NANOS_PER_S, durationAndSizeAttributes, context);
|
||||
Long requestLength =
|
||||
getAttribute(
|
||||
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH, endAttributes, state.startAttributes());
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.google.auto.value.AutoValue;
|
|||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogram;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogramBuilder;
|
||||
import io.opentelemetry.api.metrics.LongHistogram;
|
||||
import io.opentelemetry.api.metrics.LongUpDownCounter;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
|
@ -32,7 +33,7 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
public final class HttpServerMetrics implements OperationListener {
|
||||
|
||||
private static final double NANOS_PER_MS = TimeUnit.MILLISECONDS.toNanos(1);
|
||||
private static final double NANOS_PER_S = TimeUnit.SECONDS.toNanos(1);
|
||||
|
||||
private static final ContextKey<State> HTTP_SERVER_REQUEST_METRICS_STATE =
|
||||
ContextKey.named("http-server-request-metrics-state");
|
||||
|
@ -61,12 +62,13 @@ public final class HttpServerMetrics implements OperationListener {
|
|||
.setDescription("The number of concurrent HTTP requests that are currently in-flight")
|
||||
.build();
|
||||
|
||||
duration =
|
||||
DoubleHistogramBuilder durationBuilder =
|
||||
meter
|
||||
.histogramBuilder("http.server.duration")
|
||||
.setUnit("ms")
|
||||
.setDescription("The duration of the inbound HTTP request")
|
||||
.build();
|
||||
.setUnit("s")
|
||||
.setDescription("The duration of the inbound HTTP request");
|
||||
HistogramAdviceUtil.setHttpDurationBuckets(durationBuilder);
|
||||
duration = durationBuilder.build();
|
||||
requestSize =
|
||||
meter
|
||||
.histogramBuilder("http.server.request.size")
|
||||
|
@ -108,7 +110,7 @@ public final class HttpServerMetrics implements OperationListener {
|
|||
Attributes durationAndSizeAttributes =
|
||||
applyServerDurationAndSizeView(state.startAttributes(), endAttributes);
|
||||
duration.record(
|
||||
(endNanos - state.startTimeNanos()) / NANOS_PER_MS, durationAndSizeAttributes, context);
|
||||
(endNanos - state.startTimeNanos()) / NANOS_PER_S, durationAndSizeAttributes, context);
|
||||
Long requestLength =
|
||||
getAttribute(
|
||||
SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH, endAttributes, state.startAttributes());
|
||||
|
|
|
@ -24,6 +24,9 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
class HttpClientMetricsTest {
|
||||
|
||||
static final double[] DURATION_BUCKETS =
|
||||
HistogramAdviceUtil.DURATION_SECONDS_BUCKETS.stream().mapToDouble(d -> d).toArray();
|
||||
|
||||
@Test
|
||||
void collectsMetrics() {
|
||||
InMemoryMetricReader metricReader = InMemoryMetricReader.create();
|
||||
|
@ -79,13 +82,13 @@ class HttpClientMetricsTest {
|
|||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("http.client.duration")
|
||||
.hasUnit("ms")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(150 /* millis */)
|
||||
.hasSum(0.15 /* seconds */)
|
||||
.hasAttributesSatisfying(
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, 200),
|
||||
|
@ -99,7 +102,8 @@ class HttpClientMetricsTest {
|
|||
exemplar ->
|
||||
exemplar
|
||||
.hasTraceId("ff01020304050600ff0a0b0c0d0e0f00")
|
||||
.hasSpanId("090a0b0c0d0e0f00")))),
|
||||
.hasSpanId("090a0b0c0d0e0f00"))
|
||||
.hasBucketBoundaries(DURATION_BUCKETS))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("http.client.request.size")
|
||||
|
@ -158,7 +162,8 @@ class HttpClientMetricsTest {
|
|||
.hasName("http.client.duration")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(point -> point.hasSum(300 /* millis */))),
|
||||
histogram.hasPointsSatisfying(
|
||||
point -> point.hasSum(0.3 /* seconds */))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("http.client.request.size")
|
||||
|
|
|
@ -25,6 +25,9 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
class HttpServerMetricsTest {
|
||||
|
||||
static final double[] DURATION_BUCKETS =
|
||||
HistogramAdviceUtil.DURATION_SECONDS_BUCKETS.stream().mapToDouble(d -> d).toArray();
|
||||
|
||||
@Test
|
||||
void collectsMetrics() {
|
||||
InMemoryMetricReader metricReader = InMemoryMetricReader.create();
|
||||
|
@ -149,13 +152,13 @@ class HttpServerMetricsTest {
|
|||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("http.server.duration")
|
||||
.hasUnit("ms")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(150 /* millis */)
|
||||
.hasSum(0.15 /* seconds */)
|
||||
.hasAttributesSatisfying(
|
||||
equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
|
||||
equalTo(SemanticAttributes.HTTP_STATUS_CODE, 200),
|
||||
|
@ -168,7 +171,8 @@ class HttpServerMetricsTest {
|
|||
exemplar ->
|
||||
exemplar
|
||||
.hasTraceId(spanContext1.getTraceId())
|
||||
.hasSpanId(spanContext1.getSpanId())))),
|
||||
.hasSpanId(spanContext1.getSpanId()))
|
||||
.hasBucketBoundaries(DURATION_BUCKETS))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("http.server.request.size")
|
||||
|
@ -242,7 +246,7 @@ class HttpServerMetricsTest {
|
|||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(300 /* millis */)
|
||||
.hasSum(0.3 /* seconds */)
|
||||
.hasExemplarsSatisfying(
|
||||
exemplar ->
|
||||
exemplar
|
||||
|
@ -304,13 +308,13 @@ class HttpServerMetricsTest {
|
|||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("http.server.duration")
|
||||
.hasUnit("ms")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(100 /* millis */)
|
||||
.hasSum(0.100 /* seconds */)
|
||||
.hasAttributesSatisfying(
|
||||
equalTo(SemanticAttributes.HTTP_SCHEME, "https"),
|
||||
equalTo(SemanticAttributes.NET_HOST_NAME, "host"),
|
||||
|
|
Loading…
Reference in New Issue