diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/ClientHandlerInstrumentation.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/ClientHandlerInstrumentation.java index 5a550ac23881..50aeb45e631d 100644 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/ClientHandlerInstrumentation.java +++ b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/ClientHandlerInstrumentation.java @@ -10,7 +10,7 @@ import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext; -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1.JaxRsClientV1Tracer.tracer; +import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1.JaxRsClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; @@ -56,14 +56,15 @@ public static void onEnter( // WARNING: this might be a chain...so we only have to trace the first in the chain. boolean isRootClientHandler = null == request.getProperties().get(CONTEXT_ATTRIBUTE); Context parentContext = currentContext(); - if (isRootClientHandler && tracer().shouldStartSpan(parentContext)) { - context = tracer().startSpan(parentContext, request, request); + if (isRootClientHandler && instrumenter().shouldStart(parentContext, request)) { + context = instrumenter().start(parentContext, request); scope = context.makeCurrent(); } } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void onExit( + @Advice.Argument(0) ClientRequest request, @Advice.Return ClientResponse response, @Advice.Thrown Throwable throwable, @Advice.Local("otelContext") Context context, @@ -73,11 +74,7 @@ public static void onExit( } scope.close(); - if (throwable != null) { - tracer().endExceptionally(context, throwable); - } else { - tracer().end(context, response); - } + instrumenter().end(context, request, response, throwable); } } } diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientHttpAttributesExtractor.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientHttpAttributesExtractor.java new file mode 100644 index 000000000000..8d3cb51459ea --- /dev/null +++ b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientHttpAttributesExtractor.java @@ -0,0 +1,108 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; + +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.checkerframework.checker.nullness.qual.Nullable; + +final class JaxRsClientHttpAttributesExtractor + extends HttpAttributesExtractor { + + @Override + protected @Nullable String method(ClientRequest httpRequest) { + return httpRequest.getMethod(); + } + + @Override + protected String url(ClientRequest httpRequest) { + return httpRequest.getURI().toString(); + } + + @Override + protected @Nullable String target(ClientRequest httpRequest) { + StringBuilder result = new StringBuilder(); + String path = httpRequest.getURI().getPath(); + if (path != null) { + result.append(path); + } + String query = httpRequest.getURI().getQuery(); + if (query != null) { + result.append('?'); + result.append(query); + } + String fragment = httpRequest.getURI().getFragment(); + if (fragment != null) { + result.append('#'); + result.append(fragment); + } + return result.length() > 0 ? result.toString() : null; + } + + @Override + protected @Nullable String host(ClientRequest httpRequest) { + return httpRequest.getURI().getHost(); + } + + @Override + protected @Nullable String scheme(ClientRequest httpRequest) { + return httpRequest.getURI().getScheme(); + } + + @Override + protected @Nullable String userAgent(ClientRequest httpRequest) { + Object header = httpRequest.getHeaders().getFirst("User-Agent"); + return header != null ? header.toString() : null; + } + + @Override + protected @Nullable Long requestContentLength( + ClientRequest httpRequest, @Nullable ClientResponse httpResponse) { + return null; + } + + @Override + protected @Nullable Long requestContentLengthUncompressed( + ClientRequest httpRequest, @Nullable ClientResponse httpResponse) { + return null; + } + + @Override + protected String flavor(ClientRequest httpRequest, @Nullable ClientResponse httpResponse) { + return SemanticAttributes.HttpFlavorValues.HTTP_1_1; + } + + @Override + protected @Nullable Integer statusCode(ClientRequest httpRequest, ClientResponse httpResponse) { + return httpResponse.getStatus(); + } + + @Override + protected @Nullable Long responseContentLength( + ClientRequest httpRequest, ClientResponse httpResponse) { + int length = httpResponse.getLength(); + return length != -1 ? (long) length : null; + } + + @Override + protected @Nullable Long responseContentLengthUncompressed( + ClientRequest httpRequest, ClientResponse httpResponse) { + return null; + } + + @Override + protected @Nullable String route(ClientRequest httpRequest) { + return null; + } + + @Override + protected @Nullable String serverName( + ClientRequest httpRequest, @Nullable ClientResponse httpResponse) { + return null; + } +} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientNetAttributesExtractor.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientNetAttributesExtractor.java new file mode 100644 index 000000000000..eb80e0166a7f --- /dev/null +++ b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientNetAttributesExtractor.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; + +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor; +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; +import org.checkerframework.checker.nullness.qual.Nullable; + +final class JaxRsClientNetAttributesExtractor + extends NetAttributesExtractor { + + @Override + public String transport(ClientRequest request) { + return SemanticAttributes.NetTransportValues.IP_TCP; + } + + @Override + public @Nullable String peerName(ClientRequest request, @Nullable ClientResponse response) { + return request.getURI().getHost(); + } + + @Override + public Integer peerPort(ClientRequest request, @Nullable ClientResponse response) { + int port = request.getURI().getPort(); + if (port != -1) { + return port; + } + return null; + } + + @Override + public @Nullable String peerIp(ClientRequest request, @Nullable ClientResponse response) { + return null; + } +} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientSingletons.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientSingletons.java new file mode 100644 index 000000000000..28333482f0bd --- /dev/null +++ b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientSingletons.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; + +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientMetrics; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor; +import io.opentelemetry.javaagent.instrumentation.api.instrumenter.PeerServiceAttributesExtractor; + +public class JaxRsClientSingletons { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jaxrs-client-1.1"; + + private static final Instrumenter INSTRUMENTER; + + static { + HttpAttributesExtractor httpAttributesExtractor = + new JaxRsClientHttpAttributesExtractor(); + SpanNameExtractor spanNameExtractor = + HttpSpanNameExtractor.create(httpAttributesExtractor); + SpanStatusExtractor spanStatusExtractor = + HttpSpanStatusExtractor.create(httpAttributesExtractor); + JaxRsClientNetAttributesExtractor netAttributesExtractor = + new JaxRsClientNetAttributesExtractor(); + + INSTRUMENTER = + Instrumenter.newBuilder( + GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor) + .setSpanStatusExtractor(spanStatusExtractor) + .addAttributesExtractor(httpAttributesExtractor) + .addAttributesExtractor(netAttributesExtractor) + .addAttributesExtractor(PeerServiceAttributesExtractor.create(netAttributesExtractor)) + .addRequestMetrics(HttpClientMetrics.get()) + .newClientInstrumenter(new InjectAdapter()); + } + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + private JaxRsClientSingletons() {} +} diff --git a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientV1Tracer.java b/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientV1Tracer.java deleted file mode 100644 index 2709f3eb54d0..000000000000 --- a/instrumentation/jaxrs-client/jaxrs-client-1.1/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jaxrsclient/v1_1/JaxRsClientV1Tracer.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1; - -import static io.opentelemetry.javaagent.instrumentation.jaxrsclient.v1_1.InjectAdapter.SETTER; - -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; -import io.opentelemetry.context.propagation.TextMapSetter; -import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer; -import io.opentelemetry.instrumentation.api.tracer.net.NetPeerAttributes; -import java.net.URI; - -public class JaxRsClientV1Tracer - extends HttpClientTracer { - private static final JaxRsClientV1Tracer TRACER = new JaxRsClientV1Tracer(); - - private JaxRsClientV1Tracer() { - super(NetPeerAttributes.INSTANCE); - } - - public static JaxRsClientV1Tracer tracer() { - return TRACER; - } - - @Override - protected String method(ClientRequest httpRequest) { - return httpRequest.getMethod(); - } - - @Override - protected URI url(ClientRequest httpRequest) { - return httpRequest.getURI(); - } - - @Override - protected Integer status(ClientResponse clientResponse) { - return clientResponse.getStatus(); - } - - @Override - protected String requestHeader(ClientRequest clientRequest, String name) { - Object header = clientRequest.getHeaders().getFirst(name); - return header != null ? header.toString() : null; - } - - @Override - protected String responseHeader(ClientResponse clientResponse, String name) { - return clientResponse.getHeaders().getFirst(name); - } - - @Override - protected TextMapSetter getSetter() { - return SETTER; - } - - @Override - protected String getInstrumentationName() { - return "io.opentelemetry.jaxrs-client-1.1"; - } -}