From 7bbd787c8387b54adfa6488977cbe69c714f304b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Sun, 2 Jun 2024 18:45:46 +0800 Subject: [PATCH 01/20] support jettyclient 12 --- .../javaagent/build.gradle.kts | 24 ++++ .../JettyHttpClient12Instrumentation.java | 124 ++++++++++++++++ ...ettyHttpClient12InstrumentationModule.java | 34 +++++ ...pClient12RespListenersInstrumentation.java | 121 ++++++++++++++++ .../v12_0/JettyHttpClientSingletons.java | 45 ++++++ .../v12_0/JettyHttpClient12AgentTest.java | 25 ++++ .../library/build.gradle.kts | 14 ++ .../v12_0/internal/HttpHeaderSetter.java | 24 ++++ .../JettyClientHttpAttributesGetter.java | 87 ++++++++++++ .../JettyClientInstrumenterFactory.java | 73 ++++++++++ .../JettyHttpClient12TracingInterceptor.java | 100 +++++++++++++ .../testing/build.gradle.kts | 14 ++ .../v12_0/AbstractJettyClient12Test.java | 133 ++++++++++++++++++ 13 files changed, 818 insertions(+) create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts new file mode 100644 index 000000000000..44da2368a611 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts @@ -0,0 +1,24 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("org.eclipse.jetty") + module.set("jetty-client") + versions.set("[12,)") + } +} + +// We do not want to support alpha or beta version +val jettyVers_base12 = "12.0.0" + +dependencies { + implementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:library")) + + library("org.eclipse.jetty:jetty-client:$jettyVers_base12") + + testImplementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:testing")) + + latestDepTestLibrary("org.eclipse.jetty:jetty-client:12.+") // documented limitation +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java new file mode 100644 index 000000000000..025b27457962 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -0,0 +1,124 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.JETTY_CLIENT_CONTEXT_KEY; +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.instrumenter; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.nameContains; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.util.VirtualField; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClient12TracingInterceptor; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.transport.HttpRequest; + +public class JettyHttpClient12Instrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("org.eclipse.jetty.client.transport.HttpRequest"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isMethod() + .and(named("send")) + .and(takesArgument(0, named("org.eclipse.jetty.client.Response$CompleteListener"))), + JettyHttpClient12Instrumentation.class.getName() + "$JettyHttpClient12SendAdvice"); + // For request listeners + transformer.applyAdviceToMethod( + isMethod().and(nameContains("notify")), + JettyHttpClient12Instrumentation.class.getName() + "$JettyHttpClient12NotifyAdvice"); + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12SendAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterSend( + @Advice.This HttpRequest request, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + // start span + Context parentContext = Context.current(); + JettyHttpClient12TracingInterceptor interceptor = + new JettyHttpClient12TracingInterceptor(parentContext, instrumenter()); + interceptor.attachToRequest(request); + context = interceptor.getContext(); + if (context == null) { + return; + } + // set context for responseListeners + VirtualField virtualField = VirtualField.find(Request.class, Context.class); + virtualField.set(request, parentContext); + request.attribute(JETTY_CLIENT_CONTEXT_KEY, parentContext); + + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitSend( + @Advice.This HttpRequest request, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + // not ending span here unless error, span ended in the interceptor + scope.close(); + if (throwable != null) { + instrumenter().end(context, request, null, throwable); + } + } + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12NotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterNotify( + @Advice.This HttpRequest request, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (!request.getAttributes().containsKey(JETTY_CLIENT_CONTEXT_KEY)) { + return; + } + context = (Context) request.getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + if (context == null) { + return; + } + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitNotify( + @Advice.This HttpRequest request, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + // not ending span here unless error, span ended in the interceptor + scope.close(); + if (throwable != null) { + instrumenter().end(context, request, null, throwable); + } + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java new file mode 100644 index 000000000000..0b52bcc0248f --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.Arrays; +import java.util.List; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumentationModule.class) +public class JettyHttpClient12InstrumentationModule extends InstrumentationModule { + public JettyHttpClient12InstrumentationModule() { + super("jetty-httpclient", "jetty-httpclient-12.0"); + } + + @Override + public List typeInstrumentations() { + return Arrays.asList( + new JettyHttpClient12Instrumentation(), + new JettyHttpClient12RespListenersInstrumentation()); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + return hasClassesNamed("org.eclipse.jetty.client.transport.HttpRequest"); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java new file mode 100644 index 000000000000..ef601a58cd92 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java @@ -0,0 +1,121 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.instrumenter; +import static net.bytebuddy.matcher.ElementMatchers.isMethod; +import static net.bytebuddy.matcher.ElementMatchers.isPublic; +import static net.bytebuddy.matcher.ElementMatchers.nameContains; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.util.VirtualField; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.Result; + +public class JettyHttpClient12RespListenersInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + return named("org.eclipse.jetty.client.transport.ResponseListeners"); + } + + @Override + public void transform(TypeTransformer transformer) { + // for response listeners + transformer.applyAdviceToMethod( + isMethod() + .and( + nameContains("notify") + .and(isPublic()) + .and(takesArgument(0, named("org.eclipse.jetty.client.Response")))), + JettyHttpClient12RespListenersInstrumentation.class.getName() + + "$JettyHttpClient12RespListenersNotifyAdvice"); + + // for complete listeners + transformer.applyAdviceToMethod( + isMethod() + .and( + nameContains("notifyComplete") + .and(isPublic()) + .and(takesArgument(0, named("org.eclipse.jetty.client.Result")))), + JettyHttpClient12RespListenersInstrumentation.class.getName() + + "$JettyHttpClient12CompleteListenersNotifyAdvice"); + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12RespListenersNotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterNotify( + @Advice.Argument(0) Response response, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + VirtualField virtualField = VirtualField.find(Request.class, Context.class); + context = virtualField.get(response.getRequest()); + if (context == null) { + return; + } + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitNotify( + @Advice.Argument(0) Response response, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + // not ending span here unless error, span ended in the interceptor + scope.close(); + if (throwable != null) { + instrumenter().end(context, response.getRequest(), response, throwable); + } + } + } + + @SuppressWarnings("unused") + public static class JettyHttpClient12CompleteListenersNotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnterComplete( + @Advice.Argument(0) Result result, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + VirtualField virtualField = VirtualField.find(Request.class, Context.class); + context = virtualField.get(result.getRequest()); + if (context == null) { + return; + } + scope = context.makeCurrent(); + } + + @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) + public static void onExitComplete( + @Advice.Argument(0) Result result, + @Advice.Thrown Throwable throwable, + @Advice.Local("otelContext") Context context, + @Advice.Local("otelScope") Scope scope) { + if (scope == null) { + return; + } + + // not ending span here unless error, span ended in the interceptor + scope.close(); + if (throwable != null) { + instrumenter().end(context, result.getRequest(), result.getResponse(), throwable); + } + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java new file mode 100644 index 000000000000..9291b3cd9115 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import static java.util.Collections.singletonList; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientHttpAttributesGetter; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientInstrumenterFactory; +import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import java.util.function.Function; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +public class JettyHttpClientSingletons { + + static final String JETTY_CLIENT_CONTEXT_KEY = "otel-jetty-client-context"; + + private static final Instrumenter INSTRUMENTER = + JettyClientInstrumenterFactory.create( + GlobalOpenTelemetry.get(), + builder -> + builder + .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) + .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) + .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), + builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), + Function.identity(), + singletonList( + HttpClientPeerServiceAttributesExtractor.create( + JettyClientHttpAttributesGetter.INSTANCE, + CommonConfig.get().getPeerServiceResolver())), + CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + + public static Instrumenter instrumenter() { + return INSTRUMENTER; + } + + private JettyHttpClientSingletons() {} +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java new file mode 100644 index 000000000000..c6792221bc97 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.AbstractJettyClient12Test; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public class JettyHttpClient12AgentTest extends AbstractJettyClient12Test { + + @Override + protected HttpClient createStandardClient() { + return new HttpClient(); + } + + @Override + protected HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory) { + HttpClient httpClient = new HttpClient(); + httpClient.setSslContextFactory(sslContextFactory); + return httpClient; + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts new file mode 100644 index 000000000000..4519f7748715 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("otel.library-instrumentation") +} + +// We do not want to support alpha or beta version +val jettyVers_base12 = "12.0.0" + +dependencies { + library("org.eclipse.jetty:jetty-client:$jettyVers_base12") + + testImplementation(project(":instrumentation:jetty-httpclient::jetty-httpclient-12.0:testing")) + + latestDepTestLibrary("org.eclipse.jetty:jetty-client:12.+") +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java new file mode 100644 index 000000000000..b094abd3a4dc --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/HttpHeaderSetter.java @@ -0,0 +1,24 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.context.propagation.TextMapSetter; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.http.HttpField; + +enum HttpHeaderSetter implements TextMapSetter { + INSTANCE; + + @Override + public void set(Request request, String key, String value) { + if (request != null) { + request.headers( + httpFields -> { + httpFields.put(new HttpField(key, value)); + }); + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java new file mode 100644 index 000000000000..3b515f261842 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java @@ -0,0 +1,87 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; +import java.util.List; +import javax.annotation.Nullable; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.http.HttpVersion; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public enum JettyClientHttpAttributesGetter + implements HttpClientAttributesGetter { + INSTANCE; + + @Override + @Nullable + public String getHttpRequestMethod(Request request) { + return request.getMethod(); + } + + @Override + @Nullable + public String getUrlFull(Request request) { + return request.getURI().toString(); + } + + @Override + public List getHttpRequestHeader(Request request, String name) { + return request.getHeaders().getValuesList(name); + } + + @Override + public Integer getHttpResponseStatusCode( + Request request, Response response, @Nullable Throwable error) { + return response.getStatus(); + } + + @Override + public List getHttpResponseHeader(Request request, Response response, String name) { + return response.getHeaders().getValuesList(name); + } + + @Nullable + @Override + public String getNetworkProtocolName(Request request, @Nullable Response response) { + return "http"; + } + + @Nullable + @Override + public String getNetworkProtocolVersion(Request request, @Nullable Response response) { + HttpVersion httpVersion = null; + if (response != null) { + httpVersion = response.getVersion(); + } + if (httpVersion == null) { + httpVersion = request.getVersion(); + } + if (httpVersion == null) { + return null; + } + String version = httpVersion.toString(); + if (version.startsWith("HTTP/")) { + version = version.substring("HTTP/".length()); + } + return version; + } + + @Override + @Nullable + public String getServerAddress(Request request) { + return request.getHost(); + } + + @Override + public Integer getServerPort(Request request) { + return request.getPort(); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java new file mode 100644 index 000000000000..52348be041cc --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java @@ -0,0 +1,73 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; +import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class JettyClientInstrumenterFactory { + + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-httpclient-12.0"; + + public static Instrumenter create( + OpenTelemetry openTelemetry, + Consumer> extractorConfigurer, + Consumer> spanNameExtractorConfigurer, + Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer, + List> additionalExtractors, + boolean emitExperimentalHttpClientMetrics) { + + JettyClientHttpAttributesGetter httpAttributesGetter = JettyClientHttpAttributesGetter.INSTANCE; + + HttpClientAttributesExtractorBuilder httpAttributesExtractorBuilder = + HttpClientAttributesExtractor.builder(httpAttributesGetter); + extractorConfigurer.accept(httpAttributesExtractorBuilder); + + HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = + HttpSpanNameExtractor.builder(httpAttributesGetter); + spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder); + SpanNameExtractor spanNameExtractor = + spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); + + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) + .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) + .addAttributesExtractor(httpAttributesExtractorBuilder.build()) + .addAttributesExtractors(additionalExtractors) + .addOperationMetrics(HttpClientMetrics.get()); + if (emitExperimentalHttpClientMetrics) { + builder + .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) + .addOperationMetrics(HttpClientExperimentalMetrics.get()); + } + + return builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); + } + + private JettyClientInstrumenterFactory() {} +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java new file mode 100644 index 000000000000..b93d3ffa76dc --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java @@ -0,0 +1,100 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.Result; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class JettyHttpClient12TracingInterceptor + implements Request.BeginListener, + Request.FailureListener, + Response.SuccessListener, + Response.FailureListener, + Response.CompleteListener { + + private static final Logger logger = + Logger.getLogger(JettyHttpClient12TracingInterceptor.class.getName()); + + private final Context parentContext; + + @Nullable private Context context; + + private final Instrumenter instrumenter; + + public JettyHttpClient12TracingInterceptor( + Context parentCtx, Instrumenter instrumenter) { + this.parentContext = parentCtx; + this.instrumenter = instrumenter; + } + + @Nullable + public Context getContext() { + return this.context; + } + + void startSpan(Request jettyRequest) { + if (jettyRequest == null) { + return; + } + if (!instrumenter.shouldStart(this.parentContext, jettyRequest)) { + return; + } + this.context = instrumenter.start(this.parentContext, jettyRequest); + } + + public void attachToRequest(Request jettyRequest) { + startSpan(jettyRequest); + jettyRequest + .onRequestBegin(this) + .onRequestFailure(this) + .onResponseFailure(this) + .onResponseSuccess(this); + } + + void closeIfPossible(Response response) { + if (this.context != null) { + instrumenter.end(this.context, response.getRequest(), response, null); + } else { + logger.fine("onComplete - could not find an otel context"); + } + } + + @Override + public void onBegin(Request request) {} + + @Override + public void onComplete(Result result) { + closeIfPossible(result.getResponse()); + } + + @Override + public void onFailure(Response response, Throwable t) { + if (this.context != null) { + instrumenter.end(this.context, response.getRequest(), response, t); + } + } + + @Override + public void onFailure(Request request, Throwable t) { + if (this.context != null) { + instrumenter.end(this.context, request, null, t); + } + } + + @Override + public void onSuccess(Response response) { + closeIfPossible(response); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts new file mode 100644 index 000000000000..3e327eba535e --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("otel.java-conventions") +} + +// We do not want to support alpha or beta version +val jettyVers_base12 = "12.0.0" + +dependencies { + api(project(":testing-common")) + + api("org.eclipse.jetty:jetty-client:$jettyVers_base12") + + implementation("io.opentelemetry:opentelemetry-api") +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java new file mode 100644 index 000000000000..2cba3a9dfdbf --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java @@ -0,0 +1,133 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import static java.util.logging.Level.FINE; + +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; +import java.net.URI; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Logger; +import org.eclipse.jetty.client.ContentResponse; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.extension.RegisterExtension; + +public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest { + + private static final Logger logger = Logger.getLogger(AbstractJettyClient12Test.class.getName()); + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); + + protected abstract HttpClient createStandardClient(); + + protected abstract HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory); + + protected HttpClient client = createStandardClient(); + + protected HttpClient httpsClient; + + Request jettyRequest = null; + + @Override + protected void configure(HttpClientTestOptions.Builder optionsBuilder) { + try { + // disable redirect tests + optionsBuilder.disableTestRedirects(); + // jetty 12 does not support to reuse request + // use request.send() twice will block the program infinitely + optionsBuilder.disableTestReusedRequest(); + // start the main Jetty HttpClient and a https client + client.setConnectTimeout(CONNECTION_TIMEOUT.toMillis()); + client.start(); + + SslContextFactory.Client tlsCtx = new SslContextFactory.Client(); + httpsClient = createHttpsClient(tlsCtx); + httpsClient.setFollowRedirects(false); + httpsClient.start(); + } catch (Throwable t) { + logger.log(FINE, t.getMessage(), t); + } + } + + @Override + public Request buildRequest(String method, URI uri, Map headers) + throws Exception { + HttpClient theClient = Objects.equals(uri.getScheme(), "https") ? httpsClient : client; + + Request request = theClient.newRequest(uri); + request.agent("Jetty"); + + request.method(method); + request.timeout(READ_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + + jettyRequest = request; + + return request; + } + + @Override + public int sendRequest(Request request, String method, URI uri, Map headers) + throws ExecutionException, InterruptedException, TimeoutException { + headers.forEach((k, v) -> request.headers(httpFields -> httpFields.put(new HttpField(k, v)))); + + ContentResponse response = request.send(); + + return response.getStatus(); + } + + @Override + public void sendRequestWithCallback( + Request request, + String method, + URI uri, + Map headers, + HttpClientResult requestResult) + throws Exception { + JettyClientListener jcl = new JettyClientListener(); + + request.onRequestFailure(jcl); + request.onResponseFailure(jcl); + headers.forEach((k, v) -> request.headers(httpFields -> httpFields.put(new HttpField(k, v)))); + + request.send( + result -> { + if (jcl.failure != null) { + requestResult.complete(jcl.failure); + return; + } + + requestResult.complete(result.getResponse().getStatus()); + }); + } + + private static class JettyClientListener + implements Request.FailureListener, Response.FailureListener { + volatile Throwable failure; + + @Override + public void onFailure(Request requestF, Throwable failure) { + this.failure = failure; + } + + @Override + public void onFailure(Response responseF, Throwable failure) { + this.failure = failure; + } + } +} From 2af2aeff8d20a20844de8a028b94086f2e36e33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 7 Jun 2024 20:18:53 +0800 Subject: [PATCH 02/20] support library instrumentation --- .../javaagent/build.gradle.kts | 7 +- .../v12_0/JettyHttpClient12AgentTest.java | 6 + .../v12_0/JettyClientTelemetry.java | 37 +++++ .../v12_0/JettyClientTelemetryBuilder.java | 156 ++++++++++++++++++ .../httpclient/v12_0/TracingHttpClient.java | 62 +++++++ .../httpclient/v12_0/TracingHttpRequest.java | 139 ++++++++++++++++ .../v12_0/JettyHttpClient12LibraryTest.java | 39 +++++ .../testing/build.gradle.kts | 5 +- .../v12_0/AbstractJettyClient12Test.java | 6 - settings.gradle.kts | 3 + 10 files changed, 444 insertions(+), 16 deletions(-) create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts index 44da2368a611..8d2d42e2eafd 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts @@ -10,15 +10,10 @@ muzzle { } } -// We do not want to support alpha or beta version -val jettyVers_base12 = "12.0.0" - dependencies { implementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:library")) - library("org.eclipse.jetty:jetty-client:$jettyVers_base12") + library("org.eclipse.jetty:jetty-client:12.0.0") testImplementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:testing")) - - latestDepTestLibrary("org.eclipse.jetty:jetty-client:12.+") // documented limitation } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java index c6792221bc97..6aff0222c2de 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java @@ -6,11 +6,17 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.AbstractJettyClient12Test; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.extension.RegisterExtension; public class JettyHttpClient12AgentTest extends AbstractJettyClient12Test { + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); + @Override protected HttpClient createStandardClient() { return new HttpClient(); diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java new file mode 100644 index 000000000000..3e123801321a --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetry.java @@ -0,0 +1,37 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.api.OpenTelemetry; +import org.eclipse.jetty.client.HttpClient; + +/** Entrypoint for instrumenting Jetty client. */ +public final class JettyClientTelemetry { + + /** Returns a new {@link JettyClientTelemetry} configured with the given {@link OpenTelemetry}. */ + public static JettyClientTelemetry create(OpenTelemetry openTelemetry) { + JettyClientTelemetryBuilder builder = builder(openTelemetry); + return builder.build(); + } + + /** + * Returns a new {@link JettyClientTelemetryBuilder} configured with the given {@link + * OpenTelemetry}. + */ + public static JettyClientTelemetryBuilder builder(OpenTelemetry openTelemetry) { + return new JettyClientTelemetryBuilder(openTelemetry); + } + + private final HttpClient httpClient; + + JettyClientTelemetry(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public HttpClient getHttpClient() { + return httpClient; + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java new file mode 100644 index 000000000000..9a91ad1805a5 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java @@ -0,0 +1,156 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; +import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; +import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; +import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientInstrumenterFactory; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; +import org.eclipse.jetty.client.HttpClientTransport; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public final class JettyClientTelemetryBuilder { + + private final OpenTelemetry openTelemetry; + private final List> additionalExtractors = + new ArrayList<>(); + private Consumer> extractorConfigurer = + builder -> {}; + private Consumer> spanNameExtractorConfigurer = + builder -> {}; + private Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer = Function.identity(); + private boolean emitExperimentalHttpClientMetrics = false; + private HttpClientTransport httpClientTransport; + private SslContextFactory.Client sslContextFactory; + + JettyClientTelemetryBuilder(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + } + + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setHttpClientTransport( + HttpClientTransport httpClientTransport) { + this.httpClientTransport = httpClientTransport; + return this; + } + + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setSslContextFactory( + SslContextFactory.Client sslContextFactory) { + this.sslContextFactory = sslContextFactory; + return this; + } + + /** + * Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented + * items. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder addAttributeExtractor( + AttributesExtractor attributesExtractor) { + additionalExtractors.add(attributesExtractor); + return this; + } + + /** + * Configures the HTTP request headers that will be captured as span attributes. + * + * @param requestHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { + extractorConfigurer = + extractorConfigurer.andThen(builder -> builder.setCapturedRequestHeaders(requestHeaders)); + return this; + } + + /** + * Configures the HTTP response headers that will be captured as span attributes. + * + * @param responseHeaders A list of HTTP header names. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { + extractorConfigurer = + extractorConfigurer.andThen(builder -> builder.setCapturedResponseHeaders(responseHeaders)); + return this; + } + + /** + * Configures the instrumentation to recognize an alternative set of HTTP request methods. + * + *

By default, this instrumentation defines "known" methods as the ones listed in RFC9110 and the PATCH + * method defined in RFC5789. + * + *

Note: calling this method overrides the default known method sets completely; it does + * not supplement it. + * + * @param knownMethods A set of recognized HTTP request methods. + * @see HttpClientAttributesExtractorBuilder#setKnownMethods(Set) + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setKnownMethods(Set knownMethods) { + extractorConfigurer = + extractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); + spanNameExtractorConfigurer = + spanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); + return this; + } + + /** + * Configures the instrumentation to emit experimental HTTP client metrics. + * + * @param emitExperimentalHttpClientMetrics {@code true} if the experimental HTTP client metrics + * are to be emitted. + */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( + boolean emitExperimentalHttpClientMetrics) { + this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + return this; + } + + /** Sets custom {@link SpanNameExtractor} via transform function. */ + @CanIgnoreReturnValue + public JettyClientTelemetryBuilder setSpanNameExtractor( + Function, ? extends SpanNameExtractor> + spanNameExtractorTransformer) { + this.spanNameExtractorTransformer = spanNameExtractorTransformer; + return this; + } + + /** + * Returns a new {@link JettyClientTelemetry} with the settings of this {@link + * JettyClientTelemetryBuilder}. + */ + public JettyClientTelemetry build() { + TracingHttpClient tracingHttpClient = + TracingHttpClient.buildNew( + JettyClientInstrumenterFactory.create( + openTelemetry, + extractorConfigurer, + spanNameExtractorConfigurer, + spanNameExtractorTransformer, + additionalExtractors, + emitExperimentalHttpClientMetrics), + sslContextFactory, + httpClientTransport); + + return new JettyClientTelemetry(tracingHttpClient); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java new file mode 100644 index 000000000000..227fd079de22 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java @@ -0,0 +1,62 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import java.net.URI; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpClientTransport; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.transport.HttpConversation; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +class TracingHttpClient extends HttpClient { + + private final Instrumenter instrumenter; + + TracingHttpClient(Instrumenter instrumenter) { + super(); + this.instrumenter = instrumenter; + } + + TracingHttpClient( + Instrumenter instrumenter, SslContextFactory.Client sslContextFactory) { + super(); + setSslContextFactory(sslContextFactory); + this.instrumenter = instrumenter; + } + + TracingHttpClient( + Instrumenter instrumenter, + HttpClientTransport transport, + SslContextFactory.Client sslContextFactory) { + super(transport); + setSslContextFactory(sslContextFactory); + this.instrumenter = instrumenter; + } + + static TracingHttpClient buildNew( + Instrumenter instrumenter, + SslContextFactory.Client sslContextFactory, + HttpClientTransport httpClientTransport) { + TracingHttpClient tracingHttpClient = null; + if (sslContextFactory != null && httpClientTransport != null) { + tracingHttpClient = + new TracingHttpClient(instrumenter, httpClientTransport, sslContextFactory); + } else if (sslContextFactory != null) { + tracingHttpClient = new TracingHttpClient(instrumenter, sslContextFactory); + } else { + tracingHttpClient = new TracingHttpClient(instrumenter); + } + return tracingHttpClient; + } + + @Override + public Request newRequest(URI uri) { + return new TracingHttpRequest(this, new HttpConversation(), uri, instrumenter); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java new file mode 100644 index 000000000000..b4ba6ce047a9 --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java @@ -0,0 +1,139 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.context.Context; +import io.opentelemetry.context.Scope; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClient12TracingInterceptor; +import java.net.URI; +import java.nio.ByteBuffer; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; +import org.eclipse.jetty.client.transport.HttpConversation; +import org.eclipse.jetty.client.transport.HttpRequest; + +public class TracingHttpRequest extends HttpRequest { + + private Context parentContext; + + private final Instrumenter instrumenter; + + public TracingHttpRequest( + HttpClient client, + HttpConversation conversation, + URI uri, + Instrumenter instrumenter) { + super(client, conversation, uri); + this.instrumenter = instrumenter; + } + + @Override + public void send(Response.CompleteListener listener) { + parentContext = Context.current(); + JettyHttpClient12TracingInterceptor interceptor = + new JettyHttpClient12TracingInterceptor(parentContext, instrumenter); + // start span + interceptor.attachToRequest(this); + super.send( + result -> { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + // async call + listener.onComplete(result); + if (scope != null) { + scope.close(); + } + }); + } + + @Override + public void notifyQueued() { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifyQueued(); + if (scope != null) { + scope.close(); + } + } + + @Override + public void notifyBegin() { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifyBegin(); + if (scope != null) { + scope.close(); + } + } + + @Override + public void notifyHeaders() { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifyHeaders(); + if (scope != null) { + scope.close(); + } + } + + @Override + public void notifyCommit() { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifyCommit(); + if (scope != null) { + scope.close(); + } + } + + @Override + public void notifyContent(ByteBuffer byteBuffer) { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifyContent(byteBuffer); + if (scope != null) { + scope.close(); + } + } + + @Override + public void notifySuccess() { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifySuccess(); + if (scope != null) { + scope.close(); + } + } + + @Override + public void notifyFailure(Throwable failure) { + Scope scope = null; + if (parentContext != null) { + scope = parentContext.makeCurrent(); + } + super.notifyFailure(failure); + if (scope != null) { + scope.close(); + } + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java new file mode 100644 index 000000000000..e7cf65fb206d --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/test/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12LibraryTest.java @@ -0,0 +1,39 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; + +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; +import java.util.Collections; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.extension.RegisterExtension; + +class JettyHttpClient12LibraryTest extends AbstractJettyClient12Test { + + @RegisterExtension + static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forLibrary(); + + @Override + protected HttpClient createStandardClient() { + return JettyClientTelemetry.builder(testing.getOpenTelemetry()) + .setCapturedRequestHeaders( + Collections.singletonList(AbstractHttpClientTest.TEST_REQUEST_HEADER)) + .setCapturedResponseHeaders( + Collections.singletonList(AbstractHttpClientTest.TEST_RESPONSE_HEADER)) + .build() + .getHttpClient(); + } + + @Override + protected HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory) { + return JettyClientTelemetry.builder(testing.getOpenTelemetry()) + .setSslContextFactory(sslContextFactory) + .build() + .getHttpClient(); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts index 3e327eba535e..6205a47c0461 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts @@ -2,13 +2,10 @@ plugins { id("otel.java-conventions") } -// We do not want to support alpha or beta version -val jettyVers_base12 = "12.0.0" - dependencies { api(project(":testing-common")) - api("org.eclipse.jetty:jetty-client:$jettyVers_base12") + api("org.eclipse.jetty:jetty-client:12.0.0") implementation("io.opentelemetry:opentelemetry-api") } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java index 2cba3a9dfdbf..9d377bf4377d 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java @@ -7,9 +7,7 @@ import static java.util.logging.Level.FINE; -import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; -import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; import java.net.URI; @@ -25,15 +23,11 @@ import org.eclipse.jetty.client.Response; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.junit.jupiter.api.extension.RegisterExtension; public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest { private static final Logger logger = Logger.getLogger(AbstractJettyClient12Test.class.getName()); - @RegisterExtension - static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); - protected abstract HttpClient createStandardClient(); protected abstract HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory); diff --git a/settings.gradle.kts b/settings.gradle.kts index 0fbabae76ce4..3cbc1080e234 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -339,6 +339,9 @@ include(":instrumentation:jetty:jetty-common:javaagent") include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:javaagent") include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:library") include(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:testing") +include(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:javaagent") +include(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:library") +include(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:testing") include(":instrumentation:jms:jms-1.1:javaagent") include(":instrumentation:jms:jms-3.0:javaagent") include(":instrumentation:jms:jms-common:bootstrap") From 2f41645de7efb7aa65906eee78c221b258105e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 7 Jun 2024 20:58:37 +0800 Subject: [PATCH 03/20] set min java version --- .../jetty-httpclient-12.0/javaagent/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts index 8d2d42e2eafd..eb483509d90b 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts @@ -10,6 +10,10 @@ muzzle { } } +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_17) +} + dependencies { implementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:library")) From aa045ea6c5ac45356665a13160c8bf1bc3a1f965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 7 Jun 2024 23:08:38 +0800 Subject: [PATCH 04/20] set library min java version --- .../jetty-httpclient-12.0/library/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts index 4519f7748715..ff676ea5efa1 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts @@ -2,6 +2,10 @@ plugins { id("otel.library-instrumentation") } +otelJava { + minJavaVersionSupported.set(JavaVersion.VERSION_17) +} + // We do not want to support alpha or beta version val jettyVers_base12 = "12.0.0" From 6c6e4bd20169df597219c1d4a908ff8270315094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Sun, 9 Jun 2024 15:20:11 +0800 Subject: [PATCH 05/20] polish code --- .../v12_0/JettyHttpClientSingletons.java | 2 +- .../v12_0/JettyHttpClient12AgentTest.java | 2 +- .../JettyHttpClient12TracingInterceptor.java | 2 +- .../v12_0/AbstractJettyClient12Test.java | 46 ++++++++++--------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java index 9291b3cd9115..1a9717b8978f 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java @@ -17,7 +17,7 @@ import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; -public class JettyHttpClientSingletons { +public final class JettyHttpClientSingletons { static final String JETTY_CLIENT_CONTEXT_KEY = "otel-jetty-client-context"; diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java index 6aff0222c2de..7884e15938e7 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12AgentTest.java @@ -12,7 +12,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.extension.RegisterExtension; -public class JettyHttpClient12AgentTest extends AbstractJettyClient12Test { +class JettyHttpClient12AgentTest extends AbstractJettyClient12Test { @RegisterExtension static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent(); diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java index b93d3ffa76dc..ac4b56eb3000 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java @@ -17,7 +17,7 @@ * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -public class JettyHttpClient12TracingInterceptor +public final class JettyHttpClient12TracingInterceptor implements Request.BeginListener, Request.FailureListener, Response.SuccessListener, diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java index 9d377bf4377d..ec96c89a393a 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java @@ -5,8 +5,6 @@ package io.opentelemetry.instrumentation.jetty.httpclient.v12_0; -import static java.util.logging.Level.FINE; - import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientResult; import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions; @@ -16,18 +14,17 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; import org.eclipse.jetty.client.ContentResponse; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest { - private static final Logger logger = Logger.getLogger(AbstractJettyClient12Test.class.getName()); - protected abstract HttpClient createStandardClient(); protected abstract HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory); @@ -38,25 +35,30 @@ public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest Date: Sun, 9 Jun 2024 17:14:21 +0800 Subject: [PATCH 06/20] modify muzzle range in jetty httpclient --- .../v12_0/JettyHttpClient12InstrumentationModule.java | 4 ++-- .../jetty-httpclient-9.2/javaagent/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java index 0b52bcc0248f..5ed35319a0aa 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java @@ -6,11 +6,11 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static java.util.Arrays.asList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; -import java.util.Arrays; import java.util.List; import net.bytebuddy.matcher.ElementMatcher; @@ -22,7 +22,7 @@ public JettyHttpClient12InstrumentationModule() { @Override public List typeInstrumentations() { - return Arrays.asList( + return asList( new JettyHttpClient12Instrumentation(), new JettyHttpClient12RespListenersInstrumentation()); } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts index 00e213117361..9426598b07a7 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts @@ -6,7 +6,7 @@ muzzle { pass { group.set("org.eclipse.jetty") module.set("jetty-client") - versions.set("[9.2,10)") + versions.set("[9.2,12)") } } From 13e9d9b978231f682e255574ce2c9b02cc07e698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Sun, 9 Jun 2024 17:23:45 +0800 Subject: [PATCH 07/20] revert muzzle range --- .../jetty-httpclient-9.2/javaagent/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts index 9426598b07a7..00e213117361 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts @@ -6,7 +6,7 @@ muzzle { pass { group.set("org.eclipse.jetty") module.set("jetty-client") - versions.set("[9.2,12)") + versions.set("[9.2,10)") } } From 9d2f2fcd23fd48096dc9b1b599be7d5b9cb6e790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Sun, 9 Jun 2024 17:33:26 +0800 Subject: [PATCH 08/20] add supported-libraries --- docs/supported-libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md index 71e9591454d2..a9babed72956 100644 --- a/docs/supported-libraries.md +++ b/docs/supported-libraries.md @@ -55,7 +55,7 @@ These are the supported libraries and frameworks: | [Dropwizard Views](https://www.dropwizard.io/en/latest/manual/views.html) | 0.7+ | N/A | Controller Spans [3] | | [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.3+ | N/A | [HTTP Server Spans], [HTTP Server Metrics] | | [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ | N/A | Provides `http.route` [2], Controller Spans [3] | -| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2+ (not including 10+ yet) | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library) | [HTTP Client Spans], [HTTP Client Metrics] | +| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2 - 10.0,
12.0+ | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library) | [HTTP Client Spans], [HTTP Client Metrics] | | [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Elasticsearch API Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) | 7.16 - 7.17.19,
8.0 - 8.9.+ [4] | N/A | [Elasticsearch Client Spans] | From e25cd90109f299048e533f2f866ce0a1ac768d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Sun, 9 Jun 2024 17:55:12 +0800 Subject: [PATCH 09/20] delete useless field in AbstractJettyClient12Test --- .../jetty/httpclient/v12_0/AbstractJettyClient12Test.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java index ec96c89a393a..b5f0b4ecdef9 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java @@ -33,8 +33,6 @@ public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest headers) request.method(method); request.timeout(READ_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); - jettyRequest = request; - return request; } From c981ca00bdf9555d9561e6b18b05a2f82f014ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 14 Jun 2024 13:31:14 +0800 Subject: [PATCH 10/20] polish code --- .../JettyHttpClient12Instrumentation.java | 10 -- ...pClient12RespListenersInstrumentation.java | 22 ++--- .../library/build.gradle.kts | 7 +- .../httpclient/v12_0/TracingHttpRequest.java | 91 +++++++++---------- .../JettyHttpClient12TracingInterceptor.java | 8 +- 5 files changed, 54 insertions(+), 84 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java index 025b27457962..ecb8172709ca 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -14,14 +14,12 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClient12TracingInterceptor; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.transport.HttpRequest; public class JettyHttpClient12Instrumentation implements TypeInstrumentation { @@ -62,8 +60,6 @@ public static void onEnterSend( return; } // set context for responseListeners - VirtualField virtualField = VirtualField.find(Request.class, Context.class); - virtualField.set(request, parentContext); request.attribute(JETTY_CLIENT_CONTEXT_KEY, parentContext); scope = context.makeCurrent(); @@ -94,9 +90,6 @@ public static void onEnterNotify( @Advice.This HttpRequest request, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - if (!request.getAttributes().containsKey(JETTY_CLIENT_CONTEXT_KEY)) { - return; - } context = (Context) request.getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); if (context == null) { return; @@ -116,9 +109,6 @@ public static void onExitNotify( // not ending span here unless error, span ended in the interceptor scope.close(); - if (throwable != null) { - instrumenter().end(context, request, null, throwable); - } } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java index ef601a58cd92..5ba33d082774 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java @@ -5,6 +5,9 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; +import java.util.Map; + +import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.JETTY_CLIENT_CONTEXT_KEY; import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; @@ -60,11 +63,16 @@ public static void onEnterNotify( @Advice.Argument(0) Response response, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - VirtualField virtualField = VirtualField.find(Request.class, Context.class); - context = virtualField.get(response.getRequest()); - if (context == null) { + Map attr = response.getRequest().getAttributes(); + if (attr == null || !attr.containsKey(JETTY_CLIENT_CONTEXT_KEY)) { return; } + // Must be a Context + Object contextObj = attr.get(JETTY_CLIENT_CONTEXT_KEY); + if (!(contextObj instanceof Context)) { + return; + } + context = (Context) contextObj; scope = context.makeCurrent(); } @@ -78,11 +86,7 @@ public static void onExitNotify( return; } - // not ending span here unless error, span ended in the interceptor scope.close(); - if (throwable != null) { - instrumenter().end(context, response.getRequest(), response, throwable); - } } } @@ -111,11 +115,7 @@ public static void onExitComplete( return; } - // not ending span here unless error, span ended in the interceptor scope.close(); - if (throwable != null) { - instrumenter().end(context, result.getRequest(), result.getResponse(), throwable); - } } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts index ff676ea5efa1..da2df5c220a1 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/build.gradle.kts @@ -6,13 +6,8 @@ otelJava { minJavaVersionSupported.set(JavaVersion.VERSION_17) } -// We do not want to support alpha or beta version -val jettyVers_base12 = "12.0.0" - dependencies { - library("org.eclipse.jetty:jetty-client:$jettyVers_base12") + library("org.eclipse.jetty:jetty-client:12.0.0") testImplementation(project(":instrumentation:jetty-httpclient::jetty-httpclient-12.0:testing")) - - latestDepTestLibrary("org.eclipse.jetty:jetty-client:12.+") } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java index b4ba6ce047a9..277e3410aeba 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java @@ -17,7 +17,7 @@ import org.eclipse.jetty.client.transport.HttpConversation; import org.eclipse.jetty.client.transport.HttpRequest; -public class TracingHttpRequest extends HttpRequest { +class TracingHttpRequest extends HttpRequest { private Context parentContext; @@ -41,99 +41,90 @@ public void send(Response.CompleteListener listener) { interceptor.attachToRequest(this); super.send( result -> { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - // async call - listener.onComplete(result); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + listener.onComplete(result); + } + } else { + listener.onComplete(result); } }); } @Override public void notifyQueued() { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifyQueued(); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifyQueued(); + } + } else { + super.notifyQueued(); } } @Override public void notifyBegin() { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifyBegin(); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifyBegin(); + } + } else { + super.notifyBegin(); } } @Override public void notifyHeaders() { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifyHeaders(); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifyHeaders(); + } + } else { + super.notifyHeaders(); } } @Override public void notifyCommit() { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifyCommit(); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifyCommit(); + } + } else { + super.notifyCommit(); } } @Override public void notifyContent(ByteBuffer byteBuffer) { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifyContent(byteBuffer); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifyContent(byteBuffer); + } + } else { + super.notifyContent(byteBuffer); } } @Override public void notifySuccess() { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifySuccess(); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifySuccess(); + } + } else { + super.notifySuccess(); } } @Override public void notifyFailure(Throwable failure) { - Scope scope = null; if (parentContext != null) { - scope = parentContext.makeCurrent(); - } - super.notifyFailure(failure); - if (scope != null) { - scope.close(); + try (Scope scope = parentContext.makeCurrent()) { + super.notifyFailure(failure); + } + } else { + super.notifyFailure(failure); } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java index ac4b56eb3000..efd1d1e5aca2 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java @@ -21,8 +21,7 @@ public final class JettyHttpClient12TracingInterceptor implements Request.BeginListener, Request.FailureListener, Response.SuccessListener, - Response.FailureListener, - Response.CompleteListener { + Response.FailureListener { private static final Logger logger = Logger.getLogger(JettyHttpClient12TracingInterceptor.class.getName()); @@ -74,11 +73,6 @@ void closeIfPossible(Response response) { @Override public void onBegin(Request request) {} - @Override - public void onComplete(Result result) { - closeIfPossible(result.getResponse()); - } - @Override public void onFailure(Response response, Throwable t) { if (this.context != null) { From 1aa49ef566f86116f8f51c688ad954b99f199e33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 14 Jun 2024 13:50:56 +0800 Subject: [PATCH 11/20] spotless apply --- .../v12_0/JettyHttpClient12RespListenersInstrumentation.java | 4 +--- .../v12_0/internal/JettyHttpClient12TracingInterceptor.java | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java index 5ba33d082774..43daaa825855 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java @@ -5,10 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; -import java.util.Map; - import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.JETTY_CLIENT_CONTEXT_KEY; -import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0.JettyHttpClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.nameContains; @@ -20,6 +17,7 @@ import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java index efd1d1e5aca2..fa6a2f3ec2a5 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java @@ -11,7 +11,6 @@ import javax.annotation.Nullable; import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; -import org.eclipse.jetty.client.Result; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at From c8765f599ba2a0576cef0df9d71e7da2bc546d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 14 Jun 2024 15:31:58 +0800 Subject: [PATCH 12/20] fix test --- ...pClient12RespListenersInstrumentation.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java index 43daaa825855..00ca596b17f7 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java @@ -14,14 +14,12 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; import org.eclipse.jetty.client.Result; @@ -62,16 +60,10 @@ public static void onEnterNotify( @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { Map attr = response.getRequest().getAttributes(); - if (attr == null || !attr.containsKey(JETTY_CLIENT_CONTEXT_KEY)) { - return; - } - // Must be a Context - Object contextObj = attr.get(JETTY_CLIENT_CONTEXT_KEY); - if (!(contextObj instanceof Context)) { - return; + context = (Context) response.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + if (context != null) { + scope = context.makeCurrent(); } - context = (Context) contextObj; - scope = context.makeCurrent(); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) @@ -95,12 +87,10 @@ public static void onEnterComplete( @Advice.Argument(0) Result result, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - VirtualField virtualField = VirtualField.find(Request.class, Context.class); - context = virtualField.get(result.getRequest()); - if (context == null) { - return; + context = (Context) result.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + if (context != null) { + scope = context.makeCurrent(); } - scope = context.makeCurrent(); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) From df00962c28f679e2202bafd5a9a4061d66223251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 14 Jun 2024 15:38:18 +0800 Subject: [PATCH 13/20] polish supported-libraries --- docs/supported-libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md index a9babed72956..6ff940217480 100644 --- a/docs/supported-libraries.md +++ b/docs/supported-libraries.md @@ -55,7 +55,7 @@ These are the supported libraries and frameworks: | [Dropwizard Views](https://www.dropwizard.io/en/latest/manual/views.html) | 0.7+ | N/A | Controller Spans [3] | | [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.3+ | N/A | [HTTP Server Spans], [HTTP Server Metrics] | | [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ | N/A | Provides `http.route` [2], Controller Spans [3] | -| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2 - 10.0,
12.0+ | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library) | [HTTP Client Spans], [HTTP Client Metrics] | +| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2 - 10.0,
12.0+ | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library)
[opentelemetry-jetty-httpclient-12.0](../instrumentation/jetty-httpclient/jetty-httpclient-12.0/library) | [HTTP Client Spans], [HTTP Client Metrics] | | [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Elasticsearch API Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) | 7.16 - 7.17.19,
8.0 - 8.9.+ [4] | N/A | [Elasticsearch Client Spans] | From e5dbf9ff9bcf8bff7f7ce051cee9945ccb5d9f0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 14 Jun 2024 22:56:58 +0800 Subject: [PATCH 14/20] polish code --- ...a => JettyClient12ResponseListenersInstrumentation.java} | 6 +++--- .../httpclient/v12_0/JettyHttpClient12Instrumentation.java | 3 --- .../v12_0/JettyHttpClient12InstrumentationModule.java | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) rename instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/{JettyHttpClient12RespListenersInstrumentation.java => JettyClient12ResponseListenersInstrumentation.java} (95%) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java similarity index 95% rename from instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java rename to instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java index 00ca596b17f7..39f3cae204d1 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12RespListenersInstrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java @@ -23,7 +23,7 @@ import org.eclipse.jetty.client.Response; import org.eclipse.jetty.client.Result; -public class JettyHttpClient12RespListenersInstrumentation implements TypeInstrumentation { +public class JettyClient12ResponseListenersInstrumentation implements TypeInstrumentation { @Override public ElementMatcher typeMatcher() { return named("org.eclipse.jetty.client.transport.ResponseListeners"); @@ -38,7 +38,7 @@ public void transform(TypeTransformer transformer) { nameContains("notify") .and(isPublic()) .and(takesArgument(0, named("org.eclipse.jetty.client.Response")))), - JettyHttpClient12RespListenersInstrumentation.class.getName() + JettyClient12ResponseListenersInstrumentation.class.getName() + "$JettyHttpClient12RespListenersNotifyAdvice"); // for complete listeners @@ -48,7 +48,7 @@ public void transform(TypeTransformer transformer) { nameContains("notifyComplete") .and(isPublic()) .and(takesArgument(0, named("org.eclipse.jetty.client.Result")))), - JettyHttpClient12RespListenersInstrumentation.class.getName() + JettyClient12ResponseListenersInstrumentation.class.getName() + "$JettyHttpClient12CompleteListenersNotifyAdvice"); } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java index ecb8172709ca..acf26c6a4961 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -99,15 +99,12 @@ public static void onEnterNotify( @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExitNotify( - @Advice.This HttpRequest request, - @Advice.Thrown Throwable throwable, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { if (scope == null) { return; } - // not ending span here unless error, span ended in the interceptor scope.close(); } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java index 5ed35319a0aa..57c489d0c96c 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java @@ -24,7 +24,7 @@ public JettyHttpClient12InstrumentationModule() { public List typeInstrumentations() { return asList( new JettyHttpClient12Instrumentation(), - new JettyHttpClient12RespListenersInstrumentation()); + new JettyClient12ResponseListenersInstrumentation()); } @Override From 6fdb1895b2484e710da9e5decf5be9c84d8d9bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Fri, 14 Jun 2024 23:16:33 +0800 Subject: [PATCH 15/20] spotless apply --- .../httpclient/v12_0/JettyHttpClient12Instrumentation.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java index acf26c6a4961..1c10a6efe04c 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -99,8 +99,7 @@ public static void onEnterNotify( @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExitNotify( - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { + @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { if (scope == null) { return; } From 5332e2d5ee96ebcc66c460ba69ddf7ffd4c75036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=89=A7=E6=80=9D?= Date: Sat, 22 Jun 2024 00:30:56 +0800 Subject: [PATCH 16/20] polish code --- .../JettyHttpClient12Instrumentation.java | 7 +- .../httpclient/v12_0/TracingHttpRequest.java | 26 +++--- .../internal/JettyClientTracingListener.java | 73 +++++++++++++++ .../JettyHttpClient12TracingInterceptor.java | 93 ------------------- 4 files changed, 88 insertions(+), 111 deletions(-) create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java delete mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java index 1c10a6efe04c..9ba900164b36 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -14,7 +14,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClient12TracingInterceptor; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientTracingListener; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -52,10 +52,7 @@ public static void onEnterSend( @Advice.Local("otelScope") Scope scope) { // start span Context parentContext = Context.current(); - JettyHttpClient12TracingInterceptor interceptor = - new JettyHttpClient12TracingInterceptor(parentContext, instrumenter()); - interceptor.attachToRequest(request); - context = interceptor.getContext(); + context = JettyClientTracingListener.handleRequest(parentContext, request, instrumenter()); if (context == null) { return; } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java index 277e3410aeba..f2366cb96233 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java @@ -8,7 +8,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClient12TracingInterceptor; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientTracingListener; import java.net.URI; import java.nio.ByteBuffer; import org.eclipse.jetty.client.HttpClient; @@ -21,6 +21,8 @@ class TracingHttpRequest extends HttpRequest { private Context parentContext; + private Context clientContext; + private final Instrumenter instrumenter; public TracingHttpRequest( @@ -35,13 +37,11 @@ public TracingHttpRequest( @Override public void send(Response.CompleteListener listener) { parentContext = Context.current(); - JettyHttpClient12TracingInterceptor interceptor = - new JettyHttpClient12TracingInterceptor(parentContext, instrumenter); - // start span - interceptor.attachToRequest(this); + // start span and attach listeners. + clientContext = JettyClientTracingListener.handleRequest(parentContext, this, instrumenter); super.send( result -> { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { listener.onComplete(result); } @@ -53,7 +53,7 @@ public void send(Response.CompleteListener listener) { @Override public void notifyQueued() { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifyQueued(); } @@ -64,7 +64,7 @@ public void notifyQueued() { @Override public void notifyBegin() { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifyBegin(); } @@ -75,7 +75,7 @@ public void notifyBegin() { @Override public void notifyHeaders() { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifyHeaders(); } @@ -86,7 +86,7 @@ public void notifyHeaders() { @Override public void notifyCommit() { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifyCommit(); } @@ -97,7 +97,7 @@ public void notifyCommit() { @Override public void notifyContent(ByteBuffer byteBuffer) { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifyContent(byteBuffer); } @@ -108,7 +108,7 @@ public void notifyContent(ByteBuffer byteBuffer) { @Override public void notifySuccess() { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifySuccess(); } @@ -119,7 +119,7 @@ public void notifySuccess() { @Override public void notifyFailure(Throwable failure) { - if (parentContext != null) { + if (clientContext != null) { try (Scope scope = parentContext.makeCurrent()) { super.notifyFailure(failure); } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java new file mode 100644 index 000000000000..1021f17821df --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java @@ -0,0 +1,73 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import javax.annotation.Nullable; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +/** + * JettyClientTracingListener performs two actions when {@link #handleRequest(Context, Request, + * Instrumenter)} is called 1. Start the CLIENT span 2. Set the listener callbacks for each + * lifecycle action that signal end of the request. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public final class JettyClientTracingListener + implements Request.BeginListener, + Request.FailureListener, + Response.SuccessListener, + Response.FailureListener { + + private final Context context; + + private final Instrumenter instrumenter; + + private JettyClientTracingListener( + Context context, Instrumenter instrumenter) { + this.context = context; + this.instrumenter = instrumenter; + } + + @Nullable + public static Context handleRequest( + Context parentContext, Request jettyRequest, Instrumenter instrumenter) { + if (!instrumenter.shouldStart(parentContext, jettyRequest)) { + return null; + } + + Context context = instrumenter.start(parentContext, jettyRequest); + + JettyClientTracingListener listener = new JettyClientTracingListener(context, instrumenter); + jettyRequest + .onRequestBegin(listener) + .onRequestFailure(listener) + .onResponseFailure(listener) + .onResponseSuccess(listener); + return context; + } + + @Override + public void onBegin(Request request) {} + + @Override + public void onFailure(Response response, Throwable t) { + instrumenter.end(this.context, response.getRequest(), response, t); + } + + @Override + public void onFailure(Request request, Throwable t) { + instrumenter.end(this.context, request, null, t); + } + + @Override + public void onSuccess(Response response) { + instrumenter.end(this.context, response.getRequest(), response, null); + } +} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java deleted file mode 100644 index fa6a2f3ec2a5..000000000000 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClient12TracingInterceptor.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; - -import io.opentelemetry.context.Context; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import java.util.logging.Logger; -import javax.annotation.Nullable; -import org.eclipse.jetty.client.Request; -import org.eclipse.jetty.client.Response; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class JettyHttpClient12TracingInterceptor - implements Request.BeginListener, - Request.FailureListener, - Response.SuccessListener, - Response.FailureListener { - - private static final Logger logger = - Logger.getLogger(JettyHttpClient12TracingInterceptor.class.getName()); - - private final Context parentContext; - - @Nullable private Context context; - - private final Instrumenter instrumenter; - - public JettyHttpClient12TracingInterceptor( - Context parentCtx, Instrumenter instrumenter) { - this.parentContext = parentCtx; - this.instrumenter = instrumenter; - } - - @Nullable - public Context getContext() { - return this.context; - } - - void startSpan(Request jettyRequest) { - if (jettyRequest == null) { - return; - } - if (!instrumenter.shouldStart(this.parentContext, jettyRequest)) { - return; - } - this.context = instrumenter.start(this.parentContext, jettyRequest); - } - - public void attachToRequest(Request jettyRequest) { - startSpan(jettyRequest); - jettyRequest - .onRequestBegin(this) - .onRequestFailure(this) - .onResponseFailure(this) - .onResponseSuccess(this); - } - - void closeIfPossible(Response response) { - if (this.context != null) { - instrumenter.end(this.context, response.getRequest(), response, null); - } else { - logger.fine("onComplete - could not find an otel context"); - } - } - - @Override - public void onBegin(Request request) {} - - @Override - public void onFailure(Response response, Throwable t) { - if (this.context != null) { - instrumenter.end(this.context, response.getRequest(), response, t); - } - } - - @Override - public void onFailure(Request request, Throwable t) { - if (this.context != null) { - instrumenter.end(this.context, request, null, t); - } - } - - @Override - public void onSuccess(Response response) { - closeIfPossible(response); - } -} From 779bfa5b40892913e346943cc5a4119384484eef Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Mon, 1 Jul 2024 17:17:56 +0300 Subject: [PATCH 17/20] simplify --- .../httpclient/v12_0/TracingHttpRequest.java | 59 +++++-------------- 1 file changed, 14 insertions(+), 45 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java index f2366cb96233..9bdc687c250d 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpRequest.java @@ -19,11 +19,8 @@ class TracingHttpRequest extends HttpRequest { - private Context parentContext; - - private Context clientContext; - private final Instrumenter instrumenter; + private Context parentContext; public TracingHttpRequest( HttpClient client, @@ -38,92 +35,64 @@ public TracingHttpRequest( public void send(Response.CompleteListener listener) { parentContext = Context.current(); // start span and attach listeners. - clientContext = JettyClientTracingListener.handleRequest(parentContext, this, instrumenter); + JettyClientTracingListener.handleRequest(parentContext, this, instrumenter); super.send( result -> { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - listener.onComplete(result); - } - } else { + try (Scope scope = openScope()) { listener.onComplete(result); } }); } + private Scope openScope() { + return parentContext != null ? parentContext.makeCurrent() : null; + } + @Override public void notifyQueued() { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifyQueued(); - } - } else { + try (Scope scope = openScope()) { super.notifyQueued(); } } @Override public void notifyBegin() { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifyBegin(); - } - } else { + try (Scope scope = openScope()) { super.notifyBegin(); } } @Override public void notifyHeaders() { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifyHeaders(); - } - } else { + try (Scope scope = openScope()) { super.notifyHeaders(); } } @Override public void notifyCommit() { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifyCommit(); - } - } else { + try (Scope scope = openScope()) { super.notifyCommit(); } } @Override public void notifyContent(ByteBuffer byteBuffer) { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifyContent(byteBuffer); - } - } else { + try (Scope scope = openScope()) { super.notifyContent(byteBuffer); } } @Override public void notifySuccess() { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifySuccess(); - } - } else { + try (Scope scope = openScope()) { super.notifySuccess(); } } @Override public void notifyFailure(Throwable failure) { - if (clientContext != null) { - try (Scope scope = parentContext.makeCurrent()) { - super.notifyFailure(failure); - } - } else { + try (Scope scope = openScope()) { super.notifyFailure(failure); } } From 53427da386f376eeb0a1150835e1a7274c5367ab Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Tue, 2 Jul 2024 15:23:06 +0300 Subject: [PATCH 18/20] small changes --- .../javaagent/build.gradle.kts | 2 ++ ...ent12ResponseListenersInstrumentation.java | 3 +- ...ettyHttpClient12InstrumentationModule.java | 7 ---- .../httpclient/v12_0/TracingHttpClient.java | 4 +-- .../JettyClientHttpAttributesGetter.java | 7 ++-- .../internal/JettyClientTracingListener.java | 14 ++------ .../v12_0/AbstractJettyClient12Test.java | 33 +++++++++---------- .../javaagent/build.gradle.kts | 2 ++ .../httpclient/v9_2/TracingHttpClient.java | 1 - .../JettyClientHttpAttributesGetter.java | 7 ++-- .../JettyHttpClient9TracingInterceptor.java | 15 ++------- .../v9_2/AbstractJettyClient9Test.java | 12 +++---- 12 files changed, 35 insertions(+), 72 deletions(-) diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts index eb483509d90b..ae4b56855e0c 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/build.gradle.kts @@ -19,5 +19,7 @@ dependencies { library("org.eclipse.jetty:jetty-client:12.0.0") + testInstrumentation(project(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:javaagent")) + testImplementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:testing")) } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java index 39f3cae204d1..940ede1b69d1 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java @@ -16,7 +16,6 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; -import java.util.Map; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -24,6 +23,7 @@ import org.eclipse.jetty.client.Result; public class JettyClient12ResponseListenersInstrumentation implements TypeInstrumentation { + @Override public ElementMatcher typeMatcher() { return named("org.eclipse.jetty.client.transport.ResponseListeners"); @@ -59,7 +59,6 @@ public static void onEnterNotify( @Advice.Argument(0) Response response, @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - Map attr = response.getRequest().getAttributes(); context = (Context) response.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); if (context != null) { scope = context.makeCurrent(); diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java index 57c489d0c96c..5d9690dbc7f4 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java @@ -5,14 +5,12 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; -import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; import static java.util.Arrays.asList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import java.util.List; -import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) public class JettyHttpClient12InstrumentationModule extends InstrumentationModule { @@ -26,9 +24,4 @@ public List typeInstrumentations() { new JettyHttpClient12Instrumentation(), new JettyClient12ResponseListenersInstrumentation()); } - - @Override - public ElementMatcher.Junction classLoaderMatcher() { - return hasClassesNamed("org.eclipse.jetty.client.transport.HttpRequest"); - } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java index 227fd079de22..6507d00bd7dd 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/TracingHttpClient.java @@ -19,13 +19,11 @@ class TracingHttpClient extends HttpClient { private final Instrumenter instrumenter; TracingHttpClient(Instrumenter instrumenter) { - super(); this.instrumenter = instrumenter; } TracingHttpClient( Instrumenter instrumenter, SslContextFactory.Client sslContextFactory) { - super(); setSslContextFactory(sslContextFactory); this.instrumenter = instrumenter; } @@ -43,7 +41,7 @@ static TracingHttpClient buildNew( Instrumenter instrumenter, SslContextFactory.Client sslContextFactory, HttpClientTransport httpClientTransport) { - TracingHttpClient tracingHttpClient = null; + TracingHttpClient tracingHttpClient; if (sslContextFactory != null && httpClientTransport != null) { tracingHttpClient = new TracingHttpClient(instrumenter, httpClientTransport, sslContextFactory); diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java index 3b515f261842..6a241120fd55 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientHttpAttributesGetter.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; +import io.opentelemetry.instrumentation.api.internal.HttpProtocolUtil; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; import java.util.List; import javax.annotation.Nullable; @@ -67,11 +68,7 @@ public String getNetworkProtocolVersion(Request request, @Nullable Response resp if (httpVersion == null) { return null; } - String version = httpVersion.toString(); - if (version.startsWith("HTTP/")) { - version = version.substring("HTTP/".length()); - } - return version; + return HttpProtocolUtil.getVersion(httpVersion.toString()); } @Override diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java index 1021f17821df..be20a319a1cc 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientTracingListener.java @@ -20,10 +20,7 @@ * at any time. */ public final class JettyClientTracingListener - implements Request.BeginListener, - Request.FailureListener, - Response.SuccessListener, - Response.FailureListener { + implements Request.FailureListener, Response.SuccessListener, Response.FailureListener { private final Context context; @@ -45,17 +42,10 @@ public static Context handleRequest( Context context = instrumenter.start(parentContext, jettyRequest); JettyClientTracingListener listener = new JettyClientTracingListener(context, instrumenter); - jettyRequest - .onRequestBegin(listener) - .onRequestFailure(listener) - .onResponseFailure(listener) - .onResponseSuccess(listener); + jettyRequest.onRequestFailure(listener).onResponseFailure(listener).onResponseSuccess(listener); return context; } - @Override - public void onBegin(Request request) {} - @Override public void onFailure(Response response, Throwable t) { instrumenter.end(this.context, response.getRequest(), response, t); diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java index b5f0b4ecdef9..f6dcf450d1d1 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/AbstractJettyClient12Test.java @@ -20,8 +20,8 @@ import org.eclipse.jetty.client.Response; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest { @@ -30,11 +30,10 @@ public abstract class AbstractJettyClient12Test extends AbstractHttpClientTest headers) - throws Exception { + public Request buildRequest(String method, URI uri, Map headers) { HttpClient theClient = Objects.equals(uri.getScheme(), "https") ? httpsClient : client; Request request = theClient.newRequest(uri); @@ -89,18 +87,17 @@ public void sendRequestWithCallback( String method, URI uri, Map headers, - HttpClientResult requestResult) - throws Exception { - JettyClientListener jcl = new JettyClientListener(); + HttpClientResult requestResult) { + JettyClientListener clientListener = new JettyClientListener(); - request.onRequestFailure(jcl); - request.onResponseFailure(jcl); + request.onRequestFailure(clientListener); + request.onResponseFailure(clientListener); headers.forEach((k, v) -> request.headers(httpFields -> httpFields.put(new HttpField(k, v)))); request.send( result -> { - if (jcl.failure != null) { - requestResult.complete(jcl.failure); + if (clientListener.failure != null) { + requestResult.complete(clientListener.failure); return; } @@ -113,12 +110,12 @@ private static class JettyClientListener volatile Throwable failure; @Override - public void onFailure(Request requestF, Throwable failure) { + public void onFailure(Request request, Throwable failure) { this.failure = failure; } @Override - public void onFailure(Response responseF, Throwable failure) { + public void onFailure(Response response, Throwable failure) { this.failure = failure; } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts index 00e213117361..71d9062f5375 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/build.gradle.kts @@ -18,6 +18,8 @@ dependencies { library("org.eclipse.jetty:jetty-client:$jettyVers_base9") + testInstrumentation(project(":instrumentation:jetty-httpclient:jetty-httpclient-12.0:javaagent")) + testImplementation(project(":instrumentation:jetty-httpclient:jetty-httpclient-9.2:testing")) latestDepTestLibrary("org.eclipse.jetty:jetty-client:9.+") // documented limitation diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java index 094b38ced322..7f89a73244f2 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/TracingHttpClient.java @@ -23,7 +23,6 @@ class TracingHttpClient extends HttpClient { private final Instrumenter instrumenter; TracingHttpClient(Instrumenter instrumenter) { - super(); this.instrumenter = instrumenter; } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java index 35212089eaf6..75609b760582 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientHttpAttributesGetter.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal; +import io.opentelemetry.instrumentation.api.internal.HttpProtocolUtil; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter; import java.util.List; import javax.annotation.Nullable; @@ -67,11 +68,7 @@ public String getNetworkProtocolVersion(Request request, @Nullable Response resp if (httpVersion == null) { return null; } - String version = httpVersion.toString(); - if (version.startsWith("HTTP/")) { - version = version.substring("HTTP/".length()); - } - return version; + return HttpProtocolUtil.getVersion(httpVersion.toString()); } @Override diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java index 818d67ce339d..5fbc11515169 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyHttpClient9TracingInterceptor.java @@ -29,8 +29,7 @@ * at any time. */ public class JettyHttpClient9TracingInterceptor - implements Request.BeginListener, - Request.FailureListener, + implements Request.FailureListener, Response.SuccessListener, Response.FailureListener, Response.CompleteListener { @@ -80,15 +79,10 @@ public void attachToRequest(Request jettyRequest) { List existingListeners = jettyRequest.getRequestListeners(null); wrapRequestListeners(existingListeners); - jettyRequest - .onRequestBegin(this) - .onRequestFailure(this) - .onResponseFailure(this) - .onResponseSuccess(this); + jettyRequest.onRequestFailure(this).onResponseFailure(this).onResponseSuccess(this); } private void wrapRequestListeners(List requestListeners) { - ListIterator iterator = requestListeners.listIterator(); while (iterator.hasNext()) { @@ -125,16 +119,12 @@ private void wrapRequestListeners(List requestListeners } private void startSpan(Request request) { - if (!instrumenter.shouldStart(this.parentContext, request)) { return; } this.context = instrumenter.start(this.parentContext, request); } - @Override - public void onBegin(Request request) {} - @Override public void onComplete(Result result) { closeIfPossible(result.getResponse()); @@ -160,7 +150,6 @@ public void onFailure(Response response, Throwable t) { } private void closeIfPossible(Response response) { - if (this.context != null) { instrumenter.end(this.context, response.getRequest(), response, null); } else { diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java index 7099694776ef..a460907a6cfe 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/testing/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/AbstractJettyClient9Test.java @@ -17,16 +17,16 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; public abstract class AbstractJettyClient9Test extends AbstractHttpClientTest { private HttpClient client; private HttpClient httpsClient; - @BeforeEach - public void before() throws Exception { + @BeforeAll + public void setup() throws Exception { // Start the main Jetty HttpClient and a https client client = createStandardClient(); client.setConnectTimeout(5000L); @@ -38,8 +38,8 @@ public void before() throws Exception { httpsClient.start(); } - @AfterEach - public void after() throws Exception { + @AfterAll + public void cleanup() throws Exception { client.stop(); httpsClient.stop(); } From 13ebb470dc70ea43d9743f0655bc369d9fc47b03 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Tue, 2 Jul 2024 16:43:38 +0300 Subject: [PATCH 19/20] apply the same refactor as was done with other http client instrumentations --- .../v12_0/JettyHttpClientSingletons.java | 25 +------ .../v12_0/JettyClientTelemetryBuilder.java | 47 +++--------- .../JettyClientInstrumenterFactory.java | 73 ------------------- ...yHttpClientInstrumenterBuilderFactory.java | 28 +++++++ 4 files changed, 43 insertions(+), 130 deletions(-) delete mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java create mode 100644 instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java index 1a9717b8978f..68a9bca5adda 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClientSingletons.java @@ -5,15 +5,10 @@ package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v12_0; -import static java.util.Collections.singletonList; - import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientHttpAttributesGetter; -import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientInstrumenterFactory; -import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; -import java.util.function.Function; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClientInstrumenterBuilderFactory; +import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; import org.eclipse.jetty.client.Request; import org.eclipse.jetty.client.Response; @@ -22,20 +17,8 @@ public final class JettyHttpClientSingletons { static final String JETTY_CLIENT_CONTEXT_KEY = "otel-jetty-client-context"; private static final Instrumenter INSTRUMENTER = - JettyClientInstrumenterFactory.create( - GlobalOpenTelemetry.get(), - builder -> - builder - .setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders()) - .setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders()) - .setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - builder -> builder.setKnownMethods(CommonConfig.get().getKnownHttpRequestMethods()), - Function.identity(), - singletonList( - HttpClientPeerServiceAttributesExtractor.create( - JettyClientHttpAttributesGetter.INSTANCE, - CommonConfig.get().getPeerServiceResolver())), - CommonConfig.get().shouldEmitExperimentalHttpClientTelemetry()); + JavaagentHttpClientInstrumenters.create( + JettyHttpClientInstrumenterBuilderFactory.create(GlobalOpenTelemetry.get())); public static Instrumenter instrumenter() { return INSTRUMENTER; diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java index 9a91ad1805a5..a914f73d266f 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/JettyClientTelemetryBuilder.java @@ -7,15 +7,13 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientInstrumenterFactory; -import java.util.ArrayList; +import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyHttpClientInstrumenterBuilderFactory; import java.util.List; import java.util.Set; -import java.util.function.Consumer; import java.util.function.Function; import org.eclipse.jetty.client.HttpClientTransport; import org.eclipse.jetty.client.Request; @@ -24,21 +22,12 @@ public final class JettyClientTelemetryBuilder { - private final OpenTelemetry openTelemetry; - private final List> additionalExtractors = - new ArrayList<>(); - private Consumer> extractorConfigurer = - builder -> {}; - private Consumer> spanNameExtractorConfigurer = - builder -> {}; - private Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer = Function.identity(); - private boolean emitExperimentalHttpClientMetrics = false; + private final DefaultHttpClientInstrumenterBuilder builder; private HttpClientTransport httpClientTransport; private SslContextFactory.Client sslContextFactory; JettyClientTelemetryBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + builder = JettyHttpClientInstrumenterBuilderFactory.create(openTelemetry); } @CanIgnoreReturnValue @@ -62,7 +51,7 @@ public JettyClientTelemetryBuilder setSslContextFactory( @CanIgnoreReturnValue public JettyClientTelemetryBuilder addAttributeExtractor( AttributesExtractor attributesExtractor) { - additionalExtractors.add(attributesExtractor); + builder.addAttributeExtractor(attributesExtractor); return this; } @@ -73,8 +62,7 @@ public JettyClientTelemetryBuilder addAttributeExtractor( */ @CanIgnoreReturnValue public JettyClientTelemetryBuilder setCapturedRequestHeaders(List requestHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedRequestHeaders(requestHeaders)); + builder.setCapturedRequestHeaders(requestHeaders); return this; } @@ -85,8 +73,7 @@ public JettyClientTelemetryBuilder setCapturedRequestHeaders(List reques */ @CanIgnoreReturnValue public JettyClientTelemetryBuilder setCapturedResponseHeaders(List responseHeaders) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setCapturedResponseHeaders(responseHeaders)); + builder.setCapturedResponseHeaders(responseHeaders); return this; } @@ -105,10 +92,7 @@ public JettyClientTelemetryBuilder setCapturedResponseHeaders(List respo */ @CanIgnoreReturnValue public JettyClientTelemetryBuilder setKnownMethods(Set knownMethods) { - extractorConfigurer = - extractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); - spanNameExtractorConfigurer = - spanNameExtractorConfigurer.andThen(builder -> builder.setKnownMethods(knownMethods)); + builder.setKnownMethods(knownMethods); return this; } @@ -121,7 +105,7 @@ public JettyClientTelemetryBuilder setKnownMethods(Set knownMethods) { @CanIgnoreReturnValue public JettyClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( boolean emitExperimentalHttpClientMetrics) { - this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; + builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics); return this; } @@ -130,7 +114,7 @@ public JettyClientTelemetryBuilder setEmitExperimentalHttpClientMetrics( public JettyClientTelemetryBuilder setSpanNameExtractor( Function, ? extends SpanNameExtractor> spanNameExtractorTransformer) { - this.spanNameExtractorTransformer = spanNameExtractorTransformer; + builder.setSpanNameExtractor(spanNameExtractorTransformer); return this; } @@ -140,16 +124,7 @@ public JettyClientTelemetryBuilder setSpanNameExtractor( */ public JettyClientTelemetry build() { TracingHttpClient tracingHttpClient = - TracingHttpClient.buildNew( - JettyClientInstrumenterFactory.create( - openTelemetry, - extractorConfigurer, - spanNameExtractorConfigurer, - spanNameExtractorTransformer, - additionalExtractors, - emitExperimentalHttpClientMetrics), - sslContextFactory, - httpClientTransport); + TracingHttpClient.buildNew(builder.build(), sslContextFactory, httpClientTransport); return new JettyClientTelemetry(tracingHttpClient); } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java deleted file mode 100644 index 52348be041cc..000000000000 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyClientInstrumenterFactory.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; -import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; -import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; -import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpClientMetrics; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; -import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Function; -import org.eclipse.jetty.client.Request; -import org.eclipse.jetty.client.Response; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class JettyClientInstrumenterFactory { - - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-httpclient-12.0"; - - public static Instrumenter create( - OpenTelemetry openTelemetry, - Consumer> extractorConfigurer, - Consumer> spanNameExtractorConfigurer, - Function, ? extends SpanNameExtractor> - spanNameExtractorTransformer, - List> additionalExtractors, - boolean emitExperimentalHttpClientMetrics) { - - JettyClientHttpAttributesGetter httpAttributesGetter = JettyClientHttpAttributesGetter.INSTANCE; - - HttpClientAttributesExtractorBuilder httpAttributesExtractorBuilder = - HttpClientAttributesExtractor.builder(httpAttributesGetter); - extractorConfigurer.accept(httpAttributesExtractorBuilder); - - HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = - HttpSpanNameExtractor.builder(httpAttributesGetter); - spanNameExtractorConfigurer.accept(httpSpanNameExtractorBuilder); - SpanNameExtractor spanNameExtractor = - spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build()); - - InstrumenterBuilder builder = - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter)) - .addAttributesExtractor(httpAttributesExtractorBuilder.build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(HttpClientMetrics.get()); - if (emitExperimentalHttpClientMetrics) { - builder - .addAttributesExtractor(HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) - .addOperationMetrics(HttpClientExperimentalMetrics.get()); - } - - return builder.buildClientInstrumenter(HttpHeaderSetter.INSTANCE); - } - - private JettyClientInstrumenterFactory() {} -} diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java new file mode 100644 index 000000000000..386a5e6c816b --- /dev/null +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v12_0/internal/JettyHttpClientInstrumenterBuilderFactory.java @@ -0,0 +1,28 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder; +import org.eclipse.jetty.client.Request; +import org.eclipse.jetty.client.Response; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class JettyHttpClientInstrumenterBuilderFactory { + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jetty-httpclient-12.0"; + + private JettyHttpClientInstrumenterBuilderFactory() {} + + public static DefaultHttpClientInstrumenterBuilder create( + OpenTelemetry openTelemetry) { + return new DefaultHttpClientInstrumenterBuilder<>( + INSTRUMENTATION_NAME, openTelemetry, JettyClientHttpAttributesGetter.INSTANCE) + .setHeaderSetter(HttpHeaderSetter.INSTANCE); + } +} From 8adc8451a36cc3f22e3408e43de8338734897eb2 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 8 Jul 2024 17:49:43 -0700 Subject: [PATCH 20/20] Update docs/supported-libraries.md --- docs/supported-libraries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md index 3e02d492a69b..5b0b780feb90 100644 --- a/docs/supported-libraries.md +++ b/docs/supported-libraries.md @@ -55,7 +55,7 @@ These are the supported libraries and frameworks: | [Dropwizard Views](https://www.dropwizard.io/en/latest/manual/views.html) | 0.7+ | N/A | Controller Spans [3] | | [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.3+ | N/A | [HTTP Server Spans], [HTTP Server Metrics] | | [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ | N/A | Provides `http.route` [2], Controller Spans [3] | -| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2 - 10.0,
12.0+ | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library)
[opentelemetry-jetty-httpclient-12.0](../instrumentation/jetty-httpclient/jetty-httpclient-12.0/library) | [HTTP Client Spans], [HTTP Client Metrics] | +| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2 - 9.4.x,
12.0+ | [opentelemetry-jetty-httpclient-9.2](../instrumentation/jetty-httpclient/jetty-httpclient-9.2/library)
[opentelemetry-jetty-httpclient-12.0](../instrumentation/jetty-httpclient/jetty-httpclient-12.0/library) | [HTTP Client Spans], [HTTP Client Metrics] | | [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ | N/A | Provides `http.route` [2], Controller Spans [3] | | [Elasticsearch API Client](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) | 7.16 - 7.17.19,
8.0 - 8.9.+ [4] | N/A | [Elasticsearch Client Spans] |