Skip to content

Commit b78e585

Browse files
committed
Use URL path template when tracing REST clients where possible
1 parent b5a3d27 commit b78e585

File tree

8 files changed

+50
-13
lines changed

8 files changed

+50
-13
lines changed

extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryTextMapPropagatorCustomizerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ void testPropagatorCustomizer_NoPropagation() {
5656

5757
List<SpanData> spans = spanExporter.getFinishedSpanItems(2);
5858
SpanData clientSpan = getSpanByKindAndParentId(spans, SpanKind.CLIENT, "0000000000000000");
59-
assertEquals("GET", clientSpan.getName());
59+
assertEquals("GET /hello", clientSpan.getName());
6060

6161
// There is a parent id, therefore propagation is working.
6262
SpanData serverSpan = getSpanByKindAndParentId(spans, SpanKind.SERVER, clientSpan.getSpanId());

extensions/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/instrumentation/RestClientOpenTelemetryTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ void client() {
7171
List<SpanData> spans = spanExporter.getFinishedSpanItems(2);
7272

7373
SpanData client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
74-
assertEquals("GET", client.getName());
74+
assertEquals("GET /hello", client.getName());
7575
assertSemanticAttribute(client, (long) HTTP_OK, HTTP_STATUS_CODE);
7676
assertSemanticAttribute(client, HttpMethod.GET, HTTP_METHOD);
7777
assertSemanticAttribute(client, uri.toString() + "hello", HTTP_URL);
@@ -96,7 +96,7 @@ void spanNameWithoutQueryString() {
9696

9797
SpanData client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
9898
assertEquals(CLIENT, client.getKind());
99-
assertEquals("GET", client.getName());
99+
assertEquals("GET /hello", client.getName());
100100
assertSemanticAttribute(client, (long) HTTP_OK, HTTP_STATUS_CODE);
101101
assertSemanticAttribute(client, HttpMethod.GET, HTTP_METHOD);
102102
assertSemanticAttribute(client, uri.toString() + "hello?query=1", HTTP_URL);
@@ -132,7 +132,7 @@ void path() {
132132

133133
SpanData client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
134134
assertEquals(CLIENT, client.getKind());
135-
assertEquals("GET", client.getName());
135+
assertEquals("GET /hello/{path}", client.getName());
136136
assertSemanticAttribute(client, (long) HTTP_OK, HTTP_STATUS_CODE);
137137
assertSemanticAttribute(client, HttpMethod.GET, HTTP_METHOD);
138138
assertSemanticAttribute(client, uri.toString() + "hello/another", HTTP_URL);

extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/restclient/OpenTelemetryClientFilter.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.opentelemetry.api.GlobalOpenTelemetry;
1919
import io.opentelemetry.api.OpenTelemetry;
20+
import io.opentelemetry.api.trace.Span;
2021
import io.opentelemetry.context.Context;
2122
import io.opentelemetry.context.Scope;
2223
import io.opentelemetry.context.propagation.TextMapSetter;
@@ -41,6 +42,7 @@ public class OpenTelemetryClientFilter implements ClientRequestFilter, ClientRes
4142
public static final String REST_CLIENT_OTEL_SPAN_CLIENT_CONTEXT = "otel.span.client.context";
4243
public static final String REST_CLIENT_OTEL_SPAN_CLIENT_PARENT_CONTEXT = "otel.span.client.parentContext";
4344
public static final String REST_CLIENT_OTEL_SPAN_CLIENT_SCOPE = "otel.span.client.scope";
45+
private static final String URL_PATH_TEMPLATE_KEY = "UrlPathTemplate";
4446

4547
/**
4648
* Property stored in the Client Request context to retrieve the captured Vert.x context.
@@ -118,6 +120,11 @@ public void filter(final ClientRequestContext request, final ClientResponseConte
118120

119121
Context spanContext = (Context) request.getProperty(REST_CLIENT_OTEL_SPAN_CLIENT_CONTEXT);
120122
try {
123+
String pathTemplate = (String) request.getProperty(URL_PATH_TEMPLATE_KEY);
124+
if (pathTemplate != null && !pathTemplate.isEmpty()) {
125+
Span.fromContext(spanContext)
126+
.updateName(request.getMethod() + " " + pathTemplate);
127+
}
121128
instrumenter.end(spanContext, request, response, null);
122129
} finally {
123130
scope.close();

extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/tracing/intrumentation/vertx/HttpInstrumenterVertxTracer.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.netty.handler.codec.http.HttpResponseStatus;
1515
import io.opentelemetry.api.OpenTelemetry;
1616
import io.opentelemetry.api.common.AttributesBuilder;
17+
import io.opentelemetry.api.trace.Span;
1718
import io.opentelemetry.context.Scope;
1819
import io.opentelemetry.context.propagation.TextMapGetter;
1920
import io.opentelemetry.context.propagation.TextMapSetter;
@@ -30,6 +31,7 @@
3031
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
3132
import io.opentelemetry.semconv.SemanticAttributes;
3233
import io.quarkus.opentelemetry.runtime.config.runtime.SemconvStabilityType;
34+
import io.smallrye.common.vertx.VertxContext;
3335
import io.vertx.core.Context;
3436
import io.vertx.core.MultiMap;
3537
import io.vertx.core.http.HttpHeaders;
@@ -42,7 +44,9 @@
4244
import io.vertx.core.net.SocketAddress;
4345
import io.vertx.core.spi.observability.HttpRequest;
4446
import io.vertx.core.spi.observability.HttpResponse;
47+
import io.vertx.core.spi.tracing.SpanKind;
4548
import io.vertx.core.spi.tracing.TagExtractor;
49+
import io.vertx.core.tracing.TracingPolicy;
4650

4751
public class HttpInstrumenterVertxTracer implements InstrumenterVertxTracer<HttpRequest, HttpResponse> {
4852
private final Instrumenter<HttpRequest, HttpResponse> serverInstrumenter;
@@ -102,6 +106,31 @@ public <R> void sendResponse(
102106
InstrumenterVertxTracer.super.sendResponse(context, response, spanOperation, failure, tagExtractor);
103107
}
104108

109+
@Override
110+
public <R> OpenTelemetryVertxTracer.SpanOperation sendRequest(Context context,
111+
SpanKind kind,
112+
TracingPolicy policy,
113+
R request,
114+
String operation,
115+
BiConsumer<String, String> headers,
116+
TagExtractor<R> tagExtractor) {
117+
OpenTelemetryVertxTracer.SpanOperation spanOperation = InstrumenterVertxTracer.super.sendRequest(context, kind, policy,
118+
request,
119+
operation, headers, tagExtractor);
120+
if (spanOperation != null) {
121+
Context runningCtx = spanOperation.getContext();
122+
if (VertxContext.isDuplicatedContext(runningCtx)) {
123+
String pathTemplate = runningCtx.getLocal("ClientUrlPathTemplate");
124+
if (pathTemplate != null && !pathTemplate.isEmpty()) {
125+
Span.fromContext(spanOperation.getSpanContext())
126+
.updateName(((HttpRequest) spanOperation.getRequest()).method().name() + " " + pathTemplate);
127+
}
128+
}
129+
}
130+
131+
return spanOperation;
132+
}
133+
105134
@Override
106135
public HttpRequest writableHeaders(
107136
final HttpRequest request, final BiConsumer<String, String> headers) {

independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/handlers/ClientObservabilityHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ public ClientObservabilityHandler(String templatePath) {
1818
@Override
1919
public void handle(RestClientRequestContext requestContext) throws Exception {
2020
requestContext.getClientFilterProperties().put("UrlPathTemplate", templatePath);
21+
requestContext.getOrCreateClientRequestContext().getContext().putLocal("ClientUrlPathTemplate", templatePath);
2122
}
2223
}

integration-tests/opentelemetry-reactive/src/test/java/io/quarkus/it/opentelemetry/reactive/OpenTelemetryReactiveClientTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void get() {
5757
// First span is the client call. It does not have a parent span.
5858
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
5959
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
60-
assertEquals("GET", client.get("name"));
60+
assertEquals("GET /reactive", client.get("name"));
6161
assertEquals(HTTP_OK, ((Map<?, ?>) client.get("attributes")).get(HTTP_STATUS_CODE.getKey()));
6262
assertEquals(HttpMethod.GET.name(), ((Map<?, ?>) client.get("attributes")).get(HTTP_METHOD.getKey()));
6363

@@ -92,7 +92,7 @@ void post() {
9292
// First span is the client call. It does not have a parent span.
9393
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
9494
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
95-
assertEquals("POST", client.get("name"));
95+
assertEquals("POST /reactive", client.get("name"));
9696
assertEquals(HTTP_OK, ((Map<?, ?>) client.get("attributes")).get(HTTP_STATUS_CODE.getKey()));
9797
assertEquals(HttpMethod.POST.name(), ((Map<?, ?>) client.get("attributes")).get(HTTP_METHOD.getKey()));
9898

integration-tests/opentelemetry-reactive/src/test/java/io/quarkus/it/opentelemetry/reactive/OpenTelemetryWithSpanAtStartupTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void testGeneratedSpansUsingRestClientReactive() {
4747

4848
// We should get one client span, from the internal method.
4949
Map<String, Object> server = getSpanByKindAndParentId(spans, CLIENT, client.get("spanId"));
50-
assertEquals("GET", server.get("name"));
50+
assertEquals("GET /stub", server.get("name"));
5151
}
5252

5353
@Startup

integration-tests/opentelemetry/src/test/java/io/quarkus/it/opentelemetry/OpenTelemetryTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ void testEmptyClientPath() {
140140
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, server.get("spanId"));
141141
assertEquals(CLIENT.toString(), client.get("kind"));
142142
verifyResource(client);
143-
assertEquals("GET", client.get("name"));
143+
assertEquals("GET /", client.get("name"));
144144
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
145145
assertTrue((Boolean) client.get("ended"));
146146
assertTrue((Boolean) client.get("parent_valid"));
@@ -206,7 +206,7 @@ void testSlashClientPath() {
206206

207207
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, server.get("spanId"));
208208
assertEquals(CLIENT.toString(), client.get("kind"));
209-
assertEquals("GET", client.get("name"));
209+
assertEquals("GET /", client.get("name"));
210210
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
211211
assertTrue((Boolean) client.get("ended"));
212212
assertTrue((Boolean) client.get("parent_valid"));
@@ -261,7 +261,7 @@ void testBaggagePath() {
261261

262262
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, server.get("spanId"));
263263
assertEquals(CLIENT.toString(), client.get("kind"));
264-
assertEquals("GET", client.get("name"));
264+
assertEquals("GET /from-baggage", client.get("name"));
265265
assertEquals("http://localhost:8081/from-baggage", client.get("attr_http.url"));
266266
assertEquals("200", client.get("attr_http.status_code"));
267267
assertEquals(client.get("parentSpanId"), server.get("spanId"));
@@ -467,7 +467,7 @@ void testClientTracing() {
467467
assertNotNull(server.get("attr_user_agent.original"));
468468

469469
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, server.get("spanId"));
470-
assertEquals("GET", client.get("name"));
470+
assertEquals("GET /client/pong/{message}", client.get("name"));
471471
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
472472
assertTrue((Boolean) client.get("ended"));
473473
assertTrue((Boolean) client.get("parent_valid"));
@@ -530,7 +530,7 @@ void testAsyncClientTracing() {
530530
assertNotNull(server.get("attr_user_agent.original"));
531531

532532
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, server.get("spanId"));
533-
assertEquals("GET", client.get("name"));
533+
assertEquals("GET /client/pong/{message}", client.get("name"));
534534
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
535535
assertTrue((Boolean) client.get("ended"));
536536
assertTrue((Boolean) client.get("parent_valid"));
@@ -602,7 +602,7 @@ void testClientTracingWithInterceptor() {
602602
assertEquals("one", fromInterceptor.get("attr_message"));
603603

604604
Map<String, Object> client = getSpanByKindAndParentId(spans, CLIENT, fromInterceptor.get("spanId"));
605-
assertEquals("GET", client.get("name"));
605+
assertEquals("GET /client/pong/{message}", client.get("name"));
606606
assertEquals(SpanKind.CLIENT.toString(), client.get("kind"));
607607
assertTrue((Boolean) client.get("ended"));
608608
assertTrue((Boolean) client.get("parent_valid"));

0 commit comments

Comments
 (0)