Skip to content

Commit 1b61652

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

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

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: 31 additions & 1 deletion
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,9 +44,12 @@
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> {
52+
private static final String URL_PATH_TEMPLATE_KEY = "UrlPathTemplate";
4853
private final Instrumenter<HttpRequest, HttpResponse> serverInstrumenter;
4954
private final Instrumenter<HttpRequest, HttpResponse> clientInstrumenter;
5055

@@ -102,6 +107,31 @@ public <R> void sendResponse(
102107
InstrumenterVertxTracer.super.sendResponse(context, response, spanOperation, failure, tagExtractor);
103108
}
104109

110+
@Override
111+
public <R> OpenTelemetryVertxTracer.SpanOperation sendRequest(Context context,
112+
SpanKind kind,
113+
TracingPolicy policy,
114+
R request,
115+
String operation,
116+
BiConsumer<String, String> headers,
117+
TagExtractor<R> tagExtractor) {
118+
OpenTelemetryVertxTracer.SpanOperation spanOperation = InstrumenterVertxTracer.super.sendRequest(context, kind, policy,
119+
request,
120+
operation, headers, tagExtractor);
121+
if (spanOperation != null) {
122+
Context runningCtx = spanOperation.getContext();
123+
if (VertxContext.isDuplicatedContext(runningCtx)) {
124+
String pathTemplate = runningCtx.getLocal(URL_PATH_TEMPLATE_KEY);
125+
if (pathTemplate != null && !pathTemplate.isEmpty()) {
126+
Span.fromContext(spanOperation.getSpanContext())
127+
.updateName(((HttpRequest) spanOperation.getRequest()).method().name() + " " + pathTemplate);
128+
}
129+
}
130+
}
131+
132+
return spanOperation;
133+
}
134+
105135
@Override
106136
public HttpRequest writableHeaders(
107137
final HttpRequest request, final BiConsumer<String, String> headers) {
@@ -150,7 +180,7 @@ private static class RouteGetter implements HttpServerRouteBiGetter<HttpRequestS
150180
public String get(final io.opentelemetry.context.Context context, final HttpRequestSpan requestSpan,
151181
final HttpResponse response) {
152182
// RESTEasy
153-
String route = requestSpan.getContext().getLocal("UrlPathTemplate");
183+
String route = requestSpan.getContext().getLocal(URL_PATH_TEMPLATE_KEY);
154184
if (route == null) {
155185
// Vert.x
156186
route = requestSpan.getContext().getLocal("VertxRoute");

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jboss.resteasy.reactive.client.handlers;
22

3+
import org.jboss.resteasy.reactive.client.impl.ClientRequestContextImpl;
34
import org.jboss.resteasy.reactive.client.impl.RestClientRequestContext;
45
import org.jboss.resteasy.reactive.client.spi.ClientRestHandler;
56

@@ -8,6 +9,7 @@
89
*/
910
@SuppressWarnings("unused")
1011
public class ClientObservabilityHandler implements ClientRestHandler {
12+
private static final String URL_PATH_TEMPLATE_KEY = "UrlPathTemplate";
1113

1214
private final String templatePath;
1315

@@ -17,6 +19,8 @@ public ClientObservabilityHandler(String templatePath) {
1719

1820
@Override
1921
public void handle(RestClientRequestContext requestContext) throws Exception {
20-
requestContext.getClientFilterProperties().put("UrlPathTemplate", templatePath);
22+
ClientRequestContextImpl clientRequestContext = requestContext.getOrCreateClientRequestContext();
23+
requestContext.getClientFilterProperties().put(URL_PATH_TEMPLATE_KEY, templatePath);
24+
clientRequestContext.getContext().putLocal(URL_PATH_TEMPLATE_KEY, templatePath);
2125
}
2226
}

0 commit comments

Comments
 (0)