Specify `http.(client|server).duration` buckets using advice API (#8435)

This commit is contained in:
Mateusz Rzeszutek 2023-05-16 17:01:18 +02:00 committed by GitHub
parent d7d629617a
commit 28cf44cef4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 22 deletions

View File

@ -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")

View File

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

View File

@ -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());

View File

@ -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());

View File

@ -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")

View File

@ -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"),