Skip to content

Commit

Permalink
Use URL path template when tracing REST clients where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
luneo7 committed Mar 18, 2024
1 parent b5a3d27 commit 1b61652
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void client() {
List<SpanData> spans = spanExporter.getFinishedSpanItems(2);

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

SpanData client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
assertEquals(CLIENT, client.getKind());
assertEquals("GET", client.getName());
assertEquals("GET /hello", client.getName());
assertSemanticAttribute(client, (long) HTTP_OK, HTTP_STATUS_CODE);
assertSemanticAttribute(client, HttpMethod.GET, HTTP_METHOD);
assertSemanticAttribute(client, uri.toString() + "hello?query=1", HTTP_URL);
Expand Down Expand Up @@ -132,7 +132,7 @@ void path() {

SpanData client = getSpanByKindAndParentId(spans, CLIENT, "0000000000000000");
assertEquals(CLIENT, client.getKind());
assertEquals("GET", client.getName());
assertEquals("GET /hello/{path}", client.getName());
assertSemanticAttribute(client, (long) HTTP_OK, HTTP_STATUS_CODE);
assertSemanticAttribute(client, HttpMethod.GET, HTTP_METHOD);
assertSemanticAttribute(client, uri.toString() + "hello/another", HTTP_URL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.TextMapSetter;
Expand All @@ -41,6 +42,7 @@ public class OpenTelemetryClientFilter implements ClientRequestFilter, ClientRes
public static final String REST_CLIENT_OTEL_SPAN_CLIENT_CONTEXT = "otel.span.client.context";
public static final String REST_CLIENT_OTEL_SPAN_CLIENT_PARENT_CONTEXT = "otel.span.client.parentContext";
public static final String REST_CLIENT_OTEL_SPAN_CLIENT_SCOPE = "otel.span.client.scope";
private static final String URL_PATH_TEMPLATE_KEY = "UrlPathTemplate";

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

Context spanContext = (Context) request.getProperty(REST_CLIENT_OTEL_SPAN_CLIENT_CONTEXT);
try {
String pathTemplate = (String) request.getProperty(URL_PATH_TEMPLATE_KEY);
if (pathTemplate != null && !pathTemplate.isEmpty()) {
Span.fromContext(spanContext)
.updateName(request.getMethod() + " " + pathTemplate);
}
instrumenter.end(spanContext, request, response, null);
} finally {
scope.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.netty.handler.codec.http.HttpResponseStatus;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope;
import io.opentelemetry.context.propagation.TextMapGetter;
import io.opentelemetry.context.propagation.TextMapSetter;
Expand All @@ -30,6 +31,7 @@
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
import io.opentelemetry.semconv.SemanticAttributes;
import io.quarkus.opentelemetry.runtime.config.runtime.SemconvStabilityType;
import io.smallrye.common.vertx.VertxContext;
import io.vertx.core.Context;
import io.vertx.core.MultiMap;
import io.vertx.core.http.HttpHeaders;
Expand All @@ -42,9 +44,12 @@
import io.vertx.core.net.SocketAddress;
import io.vertx.core.spi.observability.HttpRequest;
import io.vertx.core.spi.observability.HttpResponse;
import io.vertx.core.spi.tracing.SpanKind;
import io.vertx.core.spi.tracing.TagExtractor;
import io.vertx.core.tracing.TracingPolicy;

public class HttpInstrumenterVertxTracer implements InstrumenterVertxTracer<HttpRequest, HttpResponse> {
private static final String URL_PATH_TEMPLATE_KEY = "UrlPathTemplate";
private final Instrumenter<HttpRequest, HttpResponse> serverInstrumenter;
private final Instrumenter<HttpRequest, HttpResponse> clientInstrumenter;

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

@Override
public <R> OpenTelemetryVertxTracer.SpanOperation sendRequest(Context context,
SpanKind kind,
TracingPolicy policy,
R request,
String operation,
BiConsumer<String, String> headers,
TagExtractor<R> tagExtractor) {
OpenTelemetryVertxTracer.SpanOperation spanOperation = InstrumenterVertxTracer.super.sendRequest(context, kind, policy,
request,
operation, headers, tagExtractor);
if (spanOperation != null) {
Context runningCtx = spanOperation.getContext();
if (VertxContext.isDuplicatedContext(runningCtx)) {
String pathTemplate = runningCtx.getLocal(URL_PATH_TEMPLATE_KEY);
if (pathTemplate != null && !pathTemplate.isEmpty()) {
Span.fromContext(spanOperation.getSpanContext())
.updateName(((HttpRequest) spanOperation.getRequest()).method().name() + " " + pathTemplate);
}
}
}

return spanOperation;
}

@Override
public HttpRequest writableHeaders(
final HttpRequest request, final BiConsumer<String, String> headers) {
Expand Down Expand Up @@ -150,7 +180,7 @@ private static class RouteGetter implements HttpServerRouteBiGetter<HttpRequestS
public String get(final io.opentelemetry.context.Context context, final HttpRequestSpan requestSpan,
final HttpResponse response) {
// RESTEasy
String route = requestSpan.getContext().getLocal("UrlPathTemplate");
String route = requestSpan.getContext().getLocal(URL_PATH_TEMPLATE_KEY);
if (route == null) {
// Vert.x
route = requestSpan.getContext().getLocal("VertxRoute");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jboss.resteasy.reactive.client.handlers;

import org.jboss.resteasy.reactive.client.impl.ClientRequestContextImpl;
import org.jboss.resteasy.reactive.client.impl.RestClientRequestContext;
import org.jboss.resteasy.reactive.client.spi.ClientRestHandler;

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

private final String templatePath;

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

@Override
public void handle(RestClientRequestContext requestContext) throws Exception {
requestContext.getClientFilterProperties().put("UrlPathTemplate", templatePath);
ClientRequestContextImpl clientRequestContext = requestContext.getOrCreateClientRequestContext();
requestContext.getClientFilterProperties().put(URL_PATH_TEMPLATE_KEY, templatePath);
clientRequestContext.getContext().putLocal(URL_PATH_TEMPLATE_KEY, templatePath);
}
}

0 comments on commit 1b61652

Please sign in to comment.