Skip to content

Commit 03a1122

Browse files
feat: add instrumentation for AsyncHttpClient version 1.8 (#15195)
Co-authored-by: otelbot <[email protected]>
1 parent 272b420 commit 03a1122

File tree

26 files changed

+588
-60
lines changed

26 files changed

+588
-60
lines changed

.fossa.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,12 @@ targets:
337337
- type: gradle
338338
path: ./
339339
target: ':instrumentation:armeria:armeria-grpc-1.14:javaagent'
340+
- type: gradle
341+
path: ./
342+
target: ':instrumentation:async-http-client:async-http-client-1-common:javaagent'
343+
- type: gradle
344+
path: ./
345+
target: ':instrumentation:async-http-client:async-http-client-1.8:javaagent'
340346
- type: gradle
341347
path: ./
342348
target: ':instrumentation:async-http-client:async-http-client-1.9:javaagent'

docs/supported-libraries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ These are the supported libraries and frameworks:
4646
| [Apache Wicket](https://wicket.apache.org/) | 8.0+ | N/A | Provides `http.route` [2] |
4747
| [Armeria](https://armeria.dev) | 1.3+ | [opentelemetry-armeria-1.3](../instrumentation/armeria/armeria-1.3/library) | [HTTP Client Spans], [HTTP Client Metrics], [HTTP Server Spans], [HTTP Server Metrics] |
4848
| [Armeria gRPC](https://armeria.dev) | 1.14+ | | [RPC Client Spans], [RPC Client Metrics], [RPC Server Spans], [RPC Server Metrics] |
49-
| [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) | 1.9+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
49+
| [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) | 1.8+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
5050
| [Avaje Jex](https://avaje.io/jex/) | 3.0+ | N/A | Provides `http.route` [2] |
5151
| [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/java-handler.html) | 1.0+ | [opentelemetry-aws-lambda-core-1.0](../instrumentation/aws-lambda/aws-lambda-core-1.0/library),<br>[opentelemetry-aws-lambda-events-3.11](../instrumentation/aws-lambda/aws-lambda-events-3.11/library) | [FaaS Server Spans] |
5252
| [AWS SDK](https://aws.amazon.com/sdk-for-java/) | 1.11 - 1.12.583,<br>2.2+ | [opentelemetry-aws-sdk-1.11](../instrumentation/aws-sdk/aws-sdk-1.11/library),<br>[opentelemetry-aws-sdk-1.11-autoconfigure](../instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure),<br>[opentelemetry-aws-sdk-2.2](../instrumentation/aws-sdk/aws-sdk-2.2/library),<br>[opentelemetry-aws-sdk-2.2-autoconfigure](../instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure) | [Messaging Spans], [Database Client Spans], [Database Client Metrics]&nbsp;[6], [HTTP Client Spans], [GenAI Client Spans], [GenAI Client Metrics] |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
plugins {
2+
id("otel.javaagent-instrumentation")
3+
}
4+
5+
dependencies {
6+
compileOnly("com.ning:async-http-client:1.8.0")
7+
8+
compileOnly("com.google.auto.value:auto-value-annotations")
9+
annotationProcessor("com.google.auto.value:auto-value")
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
7+
8+
import com.google.auto.value.AutoValue;
9+
import com.ning.http.client.Request;
10+
import com.ning.http.client.Response;
11+
import io.opentelemetry.context.Context;
12+
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
13+
import javax.annotation.Nullable;
14+
15+
@AutoValue
16+
public abstract class AsyncHandlerData {
17+
18+
public static AsyncHandlerData create(
19+
Context parentContext,
20+
Context context,
21+
Request request,
22+
Instrumenter<Request, Response> instrumenter) {
23+
return new AutoValue_AsyncHandlerData(parentContext, context, request, instrumenter);
24+
}
25+
26+
public abstract Context getParentContext();
27+
28+
public abstract Context getContext();
29+
30+
public abstract Request getRequest();
31+
32+
public abstract Instrumenter<Request, Response> getInstrumenter();
33+
34+
public void end(@Nullable Response response, @Nullable Throwable throwable) {
35+
Instrumenter<Request, Response> instrumenter = getInstrumenter();
36+
instrumenter.end(getContext(), getRequest(), response, throwable);
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
7+
8+
import com.ning.http.client.Request;
9+
import javax.annotation.Nullable;
10+
11+
public interface AsyncHttpClientHelper {
12+
13+
/**
14+
* Get the full URL from the request.
15+
*
16+
* @param request the HTTP request
17+
* @return the full URL as a string, or null if it cannot be determined
18+
*/
19+
@Nullable
20+
String getUrlFull(Request request);
21+
22+
/**
23+
* Get the server address (host) from the request.
24+
*
25+
* @param request the HTTP request
26+
* @return the server address
27+
*/
28+
String getServerAddress(Request request);
29+
30+
/**
31+
* Get the server port from the request.
32+
*
33+
* @param request the HTTP request
34+
* @return the server port
35+
*/
36+
Integer getServerPort(Request request);
37+
38+
/**
39+
* Set a header on the request.
40+
*
41+
* @param request the HTTP request
42+
* @param key the header name
43+
* @param value the header value
44+
*/
45+
void setHeader(Request request, String key, String value);
46+
}
Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,38 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9;
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
7+
8+
import static java.util.Collections.emptyList;
79

810
import com.ning.http.client.Request;
911
import com.ning.http.client.Response;
1012
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter;
11-
import java.util.Collections;
1213
import java.util.List;
1314
import javax.annotation.Nullable;
1415

1516
final class AsyncHttpClientHttpAttributesGetter
1617
implements HttpClientAttributesGetter<Request, Response> {
1718

19+
private final AsyncHttpClientHelper helper;
20+
21+
AsyncHttpClientHttpAttributesGetter(AsyncHttpClientHelper helper) {
22+
this.helper = helper;
23+
}
24+
1825
@Override
1926
public String getHttpRequestMethod(Request request) {
2027
return request.getMethod();
2128
}
2229

2330
@Override
2431
public String getUrlFull(Request request) {
25-
return request.getUri().toUrl();
32+
return helper.getUrlFull(request);
2633
}
2734

2835
@Override
2936
public List<String> getHttpRequestHeader(Request request, String name) {
30-
return request.getHeaders().getOrDefault(name, Collections.emptyList());
37+
return request.getHeaders().getOrDefault(name, emptyList());
3138
}
3239

3340
@Override
@@ -38,16 +45,16 @@ public Integer getHttpResponseStatusCode(
3845

3946
@Override
4047
public List<String> getHttpResponseHeader(Request request, Response response, String name) {
41-
return response.getHeaders().getOrDefault(name, Collections.emptyList());
48+
return response.getHeaders().getOrDefault(name, emptyList());
4249
}
4350

4451
@Override
4552
public String getServerAddress(Request request) {
46-
return request.getUri().getHost();
53+
return helper.getServerAddress(request);
4754
}
4855

4956
@Override
5057
public Integer getServerPort(Request request) {
51-
return request.getUri().getPort();
58+
return helper.getServerPort(request);
5259
}
5360
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
7+
8+
import com.ning.http.client.Request;
9+
import com.ning.http.client.Response;
10+
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
11+
import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters;
12+
13+
public final class AsyncHttpClientInstrumenterFactory {
14+
15+
public static Instrumenter<Request, Response> create(
16+
String instrumentationName, AsyncHttpClientHelper helper) {
17+
AsyncHttpClientHttpAttributesGetter httpAttributesGetter =
18+
new AsyncHttpClientHttpAttributesGetter(helper);
19+
HttpHeaderSetter headerSetter = new HttpHeaderSetter(helper);
20+
21+
return JavaagentHttpClientInstrumenters.create(
22+
instrumentationName, httpAttributesGetter, headerSetter);
23+
}
24+
25+
private AsyncHttpClientInstrumenterFactory() {}
26+
}
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9;
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
77

88
import com.ning.http.client.Request;
99
import io.opentelemetry.context.propagation.TextMapSetter;
1010

11-
enum HttpHeaderSetter implements TextMapSetter<Request> {
12-
INSTANCE;
11+
final class HttpHeaderSetter implements TextMapSetter<Request> {
12+
13+
private final AsyncHttpClientHelper helper;
14+
15+
HttpHeaderSetter(AsyncHttpClientHelper helper) {
16+
this.helper = helper;
17+
}
1318

1419
@Override
1520
public void set(Request carrier, String key, String value) {
16-
carrier.getHeaders().replaceWith(key, value);
21+
helper.setHeader(carrier, key, value);
1722
}
1823
}
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9;
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
77

88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
9-
import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9.AsyncHttpClientSingletons.ASYNC_HANDLER_DATA;
10-
import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9.AsyncHttpClientSingletons.instrumenter;
9+
import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.common.VirtualFieldHelper.ASYNC_HANDLER_DATA;
1110
import static net.bytebuddy.matcher.ElementMatchers.hasSuperClass;
1211
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
1312
import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -58,7 +57,8 @@ public static Scope onEnter(
5857
return null;
5958
}
6059
ASYNC_HANDLER_DATA.set(handler, null);
61-
instrumenter().end(data.getContext(), data.getRequest(), response, null);
60+
61+
data.end(response, null);
6262
return data.getParentContext().makeCurrent();
6363
}
6464

@@ -82,7 +82,8 @@ public static Scope onEnter(
8282
return null;
8383
}
8484
ASYNC_HANDLER_DATA.set(handler, null);
85-
instrumenter().end(data.getContext(), data.getRequest(), null, throwable);
85+
86+
data.end(null, throwable);
8687
return data.getParentContext().makeCurrent();
8788
}
8889

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.asynchttpclient.common;
7+
8+
import com.ning.http.client.AsyncHandler;
9+
import io.opentelemetry.instrumentation.api.util.VirtualField;
10+
11+
public final class VirtualFieldHelper {
12+
public static final VirtualField<AsyncHandler<?>, AsyncHandlerData> ASYNC_HANDLER_DATA =
13+
VirtualField.find(AsyncHandler.class, AsyncHandlerData.class);
14+
15+
private VirtualFieldHelper() {}
16+
}

0 commit comments

Comments
 (0)