responseHeaders) {
+ 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) {
+ 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) {
+ builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics);
+ return this;
+ }
+
+ /** Sets custom {@link SpanNameExtractor} via transform function. */
+ @CanIgnoreReturnValue
+ public JettyClientTelemetryBuilder setSpanNameExtractor(
+ Function, ? extends SpanNameExtractor super Request>>
+ spanNameExtractorTransformer) {
+ builder.setSpanNameExtractor(spanNameExtractorTransformer);
+ return this;
+ }
+
+ /**
+ * Returns a new {@link JettyClientTelemetry} with the settings of this {@link
+ * JettyClientTelemetryBuilder}.
+ */
+ public JettyClientTelemetry build() {
+ TracingHttpClient tracingHttpClient =
+ 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/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..6507d00bd7dd
--- /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,60 @@
+/*
+ * 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) {
+ this.instrumenter = instrumenter;
+ }
+
+ TracingHttpClient(
+ Instrumenter instrumenter, SslContextFactory.Client sslContextFactory) {
+ 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;
+ 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..9bdc687c250d
--- /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,99 @@
+/*
+ * 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.JettyClientTracingListener;
+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;
+
+class TracingHttpRequest extends HttpRequest {
+
+ private final Instrumenter instrumenter;
+ private Context parentContext;
+
+ 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();
+ // start span and attach listeners.
+ JettyClientTracingListener.handleRequest(parentContext, this, instrumenter);
+ super.send(
+ result -> {
+ try (Scope scope = openScope()) {
+ listener.onComplete(result);
+ }
+ });
+ }
+
+ private Scope openScope() {
+ return parentContext != null ? parentContext.makeCurrent() : null;
+ }
+
+ @Override
+ public void notifyQueued() {
+ try (Scope scope = openScope()) {
+ super.notifyQueued();
+ }
+ }
+
+ @Override
+ public void notifyBegin() {
+ try (Scope scope = openScope()) {
+ super.notifyBegin();
+ }
+ }
+
+ @Override
+ public void notifyHeaders() {
+ try (Scope scope = openScope()) {
+ super.notifyHeaders();
+ }
+ }
+
+ @Override
+ public void notifyCommit() {
+ try (Scope scope = openScope()) {
+ super.notifyCommit();
+ }
+ }
+
+ @Override
+ public void notifyContent(ByteBuffer byteBuffer) {
+ try (Scope scope = openScope()) {
+ super.notifyContent(byteBuffer);
+ }
+ }
+
+ @Override
+ public void notifySuccess() {
+ try (Scope scope = openScope()) {
+ super.notifySuccess();
+ }
+ }
+
+ @Override
+ public void notifyFailure(Throwable failure) {
+ try (Scope scope = openScope()) {
+ 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/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..6a241120fd55
--- /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,84 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+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;
+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;
+ }
+ return HttpProtocolUtil.getVersion(httpVersion.toString());
+ }
+
+ @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/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..be20a319a1cc
--- /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,63 @@
+/*
+ * 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.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.onRequestFailure(listener).onResponseFailure(listener).onResponseSuccess(listener);
+ return context;
+ }
+
+ @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/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);
+ }
+}
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
new file mode 100644
index 000000000000..6205a47c0461
--- /dev/null
+++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/testing/build.gradle.kts
@@ -0,0 +1,11 @@
+plugins {
+ id("otel.java-conventions")
+}
+
+dependencies {
+ api(project(":testing-common"))
+
+ 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
new file mode 100644
index 000000000000..4f606242c9da
--- /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,122 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.jetty.httpclient.v12_0;
+
+import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
+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 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 {
+
+ protected abstract HttpClient createStandardClient();
+
+ protected abstract HttpClient createHttpsClient(SslContextFactory.Client sslContextFactory);
+
+ protected HttpClient client = createStandardClient();
+ protected HttpClient httpsClient;
+
+ @BeforeEach
+ public void before() throws Exception {
+ client.setConnectTimeout(CONNECTION_TIMEOUT.toMillis());
+ client.start();
+
+ SslContextFactory.Client tlsCtx = new SslContextFactory.Client();
+ httpsClient = createHttpsClient(tlsCtx);
+ httpsClient.setFollowRedirects(false);
+ httpsClient.start();
+ }
+
+ @AfterEach
+ public void after() throws Exception {
+ client.stop();
+ httpsClient.stop();
+ }
+
+ @Override
+ protected void configure(HttpClientTestOptions.Builder optionsBuilder) {
+ // disable redirect tests
+ optionsBuilder.disableTestRedirects();
+ // jetty 12 does not support to reuse request
+ // use request.send() twice will block the program infinitely
+ optionsBuilder.disableTestReusedRequest();
+ }
+
+ @Override
+ public Request buildRequest(String method, URI uri, Map headers) {
+ 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);
+
+ 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) {
+ JettyClientListener clientListener = new JettyClientListener();
+
+ request.onRequestFailure(clientListener);
+ request.onResponseFailure(clientListener);
+ headers.forEach((k, v) -> request.headers(httpFields -> httpFields.put(new HttpField(k, v))));
+
+ request.send(
+ result -> {
+ if (clientListener.failure != null) {
+ requestResult.complete(clientListener.failure);
+ return;
+ }
+
+ requestResult.complete(result.getResponse().getStatus());
+ });
+ }
+
+ private static class JettyClientListener
+ implements Request.FailureListener, Response.FailureListener {
+ volatile Throwable failure;
+
+ @Override
+ public void onFailure(Request request, Throwable failure) {
+ this.failure = failure;
+ }
+
+ @Override
+ 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 e89708a146e9..ffa837707f44 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/JettyClientTracingListener.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientTracingListener.java
index 844929afe81b..71909ac0557e 100644
--- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientTracingListener.java
+++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/library/src/main/java/io/opentelemetry/instrumentation/jetty/httpclient/v9_2/internal/JettyClientTracingListener.java
@@ -29,10 +29,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 static final Logger logger = Logger.getLogger(JettyClientTracingListener.class.getName());
@@ -77,11 +74,7 @@ public static Context handleRequest(
wrapRequestListeners(existingListeners, context);
JettyClientTracingListener listener = new JettyClientTracingListener(context, instrumenter);
- request
- .onRequestBegin(listener)
- .onRequestFailure(listener)
- .onResponseFailure(listener)
- .onResponseSuccess(listener);
+ request.onRequestFailure(listener).onResponseFailure(listener).onResponseSuccess(listener);
return context;
}
@@ -123,9 +116,6 @@ private static void wrapRequestListeners(
}
}
- @Override
- public void onBegin(Request request) {}
-
@Override
public void onSuccess(Response response) {
instrumenter.end(this.context, response.getRequest(), response, null);
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..9a53e6014e7a 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
@@ -19,7 +19,9 @@
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.TestInstance;
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class AbstractJettyClient9Test extends AbstractHttpClientTest {
private HttpClient client;
diff --git a/settings.gradle.kts b/settings.gradle.kts
index dbdf71f92319..7e766690e28c 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -357,6 +357,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")