Update the http.route attribute even for not sampled server spans
MODIFY
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpRouteHolder.java
instrumentation-api-semconv/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpRouteHolder.java
@@ -102,9 +102,9 @@ public final class HttpRouteHolder {
T arg1,
U arg2) {
Span serverSpan = ServerSpan.fromContextOrNull(context);
- // checking isRecording() is a helpful optimization for more expensive suppliers
- // (e.g. Spring MVC instrumentation's HandlerAdapterInstrumentation)
- if (serverSpan == null || !serverSpan.isRecording()) {
+ // even if the server span is not sampled, we have to continue - we need to compute the
+ // http.route properly so that it can be captured by the server metrics
+ if (serverSpan == null) {
return;
}
HttpRouteHolder httpRouteHolder = context.get(CONTEXT_KEY);

ADD
instrumentation-api-semconv/src/test/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpRouteHolderTest.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.api.instrumenter.http;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.SpanContext;
+import io.opentelemetry.api.trace.TraceFlags;
+import io.opentelemetry.api.trace.TraceState;
+import io.opentelemetry.context.Context;
+import io.opentelemetry.instrumentation.api.internal.SpanKey;
+import org.junit.jupiter.api.Test;
+
+class HttpRouteHolderTest {
+
+ @Test
+ void shouldSetRouteEvenIfSpanIsNotSampled() {
+ Span span =
+ Span.wrap(
+ SpanContext.create(
+ "00000000000000000000000000000042",
+ "0000000000000012",
+ TraceFlags.getDefault(),
+ TraceState.getDefault()));
+
+ Context context = Context.root();
+ context = context.with(span);
+ context = SpanKey.SERVER.storeInContext(context, span);
+ context = HttpRouteHolder.get().start(context, null, Attributes.empty());
+
+ assertNull(HttpRouteHolder.getRoute(context));
+
+ HttpRouteHolder.updateHttpRoute(context, HttpRouteSource.SERVLET, "/get/:id");
+
+ assertEquals("/get/:id", HttpRouteHolder.getRoute(context));
+ }
+
+ // TODO(mateusz): add more unit tests for HttpRouteHolder
+}

MODIFY
instrumentation/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/OpenTelemetryClient.java
instrumentation/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/OpenTelemetryClient.java
@@ -11,7 +11,6 @@ import com.linecorp.armeria.client.SimpleDecoratingHttpClient;
import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.logging.RequestLog;
-import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
@@ -36,12 +35,9 @@ final class OpenTelemetryClient extends SimpleDecoratingHttpClient {
Context context = instrumenter.start(Context.current(), ctx);
- Span span = Span.fromContext(context);
- if (span.isRecording()) {
ctx.log()
.whenComplete()
.thenAccept(log -> instrumenter.end(context, ctx, log, log.responseCause()));
- }
try (Scope ignored = context.makeCurrent()) {
return unwrap().execute(ctx, req);

MODIFY
instrumentation/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/OpenTelemetryService.java
instrumentation/armeria-1.3/library/src/main/java/io/opentelemetry/instrumentation/armeria/v1_3/OpenTelemetryService.java
@@ -11,7 +11,6 @@ import com.linecorp.armeria.common.logging.RequestLog;
import com.linecorp.armeria.server.HttpService;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.SimpleDecoratingHttpService;
-import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
@@ -36,12 +35,9 @@ final class OpenTelemetryService extends SimpleDecoratingHttpService {
Context context = instrumenter.start(parentContext, ctx);
- Span span = Span.fromContext(context);
- if (span.isRecording()) {
ctx.log()
.whenComplete()
.thenAccept(log -> instrumenter.end(context, ctx, log, log.responseCause()));
- }
try (Scope ignored = context.makeCurrent()) {
return unwrap().serve(ctx, req);

Update the http.route attribute even for not sampled server spans (#5844)