Update Apache HttpClient 4.0 to Instrumenter API (#3042)
* Update Apache HttpClient 4.0 to Instrumenter API * Update instrumentation/apache-httpclient/apache-httpclient-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachehttpclient/v4_0/ApacheHttpClientHttpAttributesExtractor.java Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>
This commit is contained in:
parent
b8a8db49c0
commit
bdfd22f8a3
|
@ -5,18 +5,20 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientInstrumenters.instrumenter;
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
|
||||||
public class ApacheHttpClientHelper {
|
public final class ApacheHttpClientHelper {
|
||||||
|
|
||||||
public static void doMethodExit(Context context, Object result, Throwable throwable) {
|
public static void doMethodExit(
|
||||||
|
Context context, HttpUriRequest request, Object result, Throwable throwable) {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
tracer().endExceptionally(context, throwable);
|
instrumenter().end(context, request, null, throwable);
|
||||||
} else if (result instanceof HttpResponse) {
|
} else if (result instanceof HttpResponse) {
|
||||||
tracer().end(context, (HttpResponse) result);
|
instrumenter().end(context, request, (HttpResponse) result, null);
|
||||||
} else {
|
} else {
|
||||||
// ended in WrappingStatusSettingResponseHandler
|
// ended in WrappingStatusSettingResponseHandler
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
|
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor;
|
||||||
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
|
import java.net.URI;
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolVersion;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
final class ApacheHttpClientHttpAttributesExtractor
|
||||||
|
extends HttpAttributesExtractor<HttpUriRequest, HttpResponse> {
|
||||||
|
|
||||||
|
private static final Logger logger =
|
||||||
|
LoggerFactory.getLogger(ApacheHttpClientHttpAttributesExtractor.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String method(HttpUriRequest request) {
|
||||||
|
return request.getMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String url(HttpUriRequest request) {
|
||||||
|
return request.getURI().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String target(HttpUriRequest request) {
|
||||||
|
URI uri = request.getURI();
|
||||||
|
String pathString = uri.getPath();
|
||||||
|
String queryString = uri.getQuery();
|
||||||
|
if (pathString != null && queryString != null) {
|
||||||
|
return pathString + "?" + queryString;
|
||||||
|
} else if (queryString != null) {
|
||||||
|
return "?" + queryString;
|
||||||
|
} else {
|
||||||
|
return pathString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String host(HttpUriRequest request) {
|
||||||
|
Header header = request.getFirstHeader("Host");
|
||||||
|
if (header != null) {
|
||||||
|
return header.getValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String scheme(HttpUriRequest request) {
|
||||||
|
return request.getURI().getScheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String userAgent(HttpUriRequest request) {
|
||||||
|
Header header = request.getFirstHeader("User-Agent");
|
||||||
|
return header != null ? header.getValue() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected Long requestContentLength(HttpUriRequest request, HttpResponse unused) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected Long requestContentLengthUncompressed(HttpUriRequest request, HttpResponse unused) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer statusCode(HttpUriRequest request, HttpResponse response) {
|
||||||
|
if (response == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return response.getStatusLine().getStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String flavor(HttpUriRequest request, HttpResponse response) {
|
||||||
|
ProtocolVersion protocolVersion = request.getRequestLine().getProtocolVersion();
|
||||||
|
String protocol = protocolVersion.getProtocol();
|
||||||
|
if (!protocol.equals("HTTP")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int major = protocolVersion.getMajor();
|
||||||
|
int minor = protocolVersion.getMinor();
|
||||||
|
if (major == 1 && minor == 0) {
|
||||||
|
return SemanticAttributes.HttpFlavorValues.HTTP_1_0;
|
||||||
|
}
|
||||||
|
if (major == 1 && minor == 1) {
|
||||||
|
return SemanticAttributes.HttpFlavorValues.HTTP_1_1;
|
||||||
|
}
|
||||||
|
if (major == 2 && minor == 0) {
|
||||||
|
return SemanticAttributes.HttpFlavorValues.HTTP_2_0;
|
||||||
|
}
|
||||||
|
logger.debug("unexpected http protocol version: " + protocolVersion);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected Long responseContentLength(HttpUriRequest request, HttpResponse response) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected Long responseContentLengthUncompressed(HttpUriRequest request, HttpResponse response) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String serverName(HttpUriRequest request, HttpResponse response) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String route(HttpUriRequest request) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String clientIp(HttpUriRequest request, HttpResponse response) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
|
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
|
||||||
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
|
||||||
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientInstrumenters.instrumenter;
|
||||||
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
|
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
|
import static net.bytebuddy.matcher.ElementMatchers.isAbstract;
|
||||||
|
@ -147,16 +147,17 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
Context parentContext = currentContext();
|
Context parentContext = currentContext();
|
||||||
if (!tracer().shouldStartSpan(parentContext)) {
|
if (!instrumenter().shouldStart(parentContext, request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context = tracer().startSpan(parentContext, request);
|
context = instrumenter().start(parentContext, request);
|
||||||
scope = context.makeCurrent();
|
scope = context.makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
public static void methodExit(
|
public static void methodExit(
|
||||||
|
@Advice.Argument(0) HttpUriRequest request,
|
||||||
@Advice.Return Object result,
|
@Advice.Return Object result,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
|
@ -166,7 +167,7 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.close();
|
scope.close();
|
||||||
ApacheHttpClientHelper.doMethodExit(context, result, throwable);
|
ApacheHttpClientHelper.doMethodExit(context, request, result, throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,21 +180,23 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
Context parentContext = currentContext();
|
Context parentContext = currentContext();
|
||||||
if (!tracer().shouldStartSpan(parentContext)) {
|
if (!instrumenter().shouldStart(parentContext, request)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context = tracer().startSpan(parentContext, request);
|
context = instrumenter().start(parentContext, request);
|
||||||
scope = context.makeCurrent();
|
scope = context.makeCurrent();
|
||||||
|
|
||||||
// Wrap the handler so we capture the status code
|
// Wrap the handler so we capture the status code
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler = new WrappingStatusSettingResponseHandler<>(context, parentContext, handler);
|
handler =
|
||||||
|
new WrappingStatusSettingResponseHandler<>(context, parentContext, handler, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||||
public static void methodExit(
|
public static void methodExit(
|
||||||
|
@Advice.Argument(0) HttpUriRequest request,
|
||||||
@Advice.Return Object result,
|
@Advice.Return Object result,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
|
@ -203,7 +206,7 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.close();
|
scope.close();
|
||||||
ApacheHttpClientHelper.doMethodExit(context, result, throwable);
|
ApacheHttpClientHelper.doMethodExit(context, request, result, throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,14 +215,18 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
public static void methodEnter(
|
public static void methodEnter(
|
||||||
@Advice.Argument(0) HttpHost host,
|
@Advice.Argument(0) HttpHost host,
|
||||||
@Advice.Argument(1) HttpRequest request,
|
@Advice.Argument(1) HttpRequest request,
|
||||||
|
@Advice.Local("otelHttpUriRequest") HttpUriRequest httpUriRequest,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
Context parentContext = currentContext();
|
Context parentContext = currentContext();
|
||||||
if (!tracer().shouldStartSpan(parentContext)) {
|
|
||||||
|
httpUriRequest = new HostAndRequestAsHttpUriRequest(host, request);
|
||||||
|
|
||||||
|
if (!instrumenter().shouldStart(parentContext, httpUriRequest)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context = tracer().startSpan(parentContext, host, request);
|
context = instrumenter().start(parentContext, httpUriRequest);
|
||||||
scope = context.makeCurrent();
|
scope = context.makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +234,7 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
public static void methodExit(
|
public static void methodExit(
|
||||||
@Advice.Return Object result,
|
@Advice.Return Object result,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
|
@Advice.Local("otelHttpUriRequest") HttpUriRequest httpUriRequest,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
|
@ -234,7 +242,7 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.close();
|
scope.close();
|
||||||
ApacheHttpClientHelper.doMethodExit(context, result, throwable);
|
ApacheHttpClientHelper.doMethodExit(context, httpUriRequest, result, throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,19 +253,22 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
@Advice.Argument(0) HttpHost host,
|
@Advice.Argument(0) HttpHost host,
|
||||||
@Advice.Argument(1) HttpRequest request,
|
@Advice.Argument(1) HttpRequest request,
|
||||||
@Advice.Argument(value = 2, readOnly = false) ResponseHandler<?> handler,
|
@Advice.Argument(value = 2, readOnly = false) ResponseHandler<?> handler,
|
||||||
|
@Advice.Local("otelHttpUriRequest") HttpUriRequest httpUriRequest,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
Context parentContext = currentContext();
|
Context parentContext = currentContext();
|
||||||
if (!tracer().shouldStartSpan(parentContext)) {
|
if (!instrumenter().shouldStart(parentContext, httpUriRequest)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
context = tracer().startSpan(parentContext, host, request);
|
context = instrumenter().start(parentContext, httpUriRequest);
|
||||||
scope = context.makeCurrent();
|
scope = context.makeCurrent();
|
||||||
|
|
||||||
// Wrap the handler so we capture the status code
|
// Wrap the handler so we capture the status code
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler = new WrappingStatusSettingResponseHandler<>(context, parentContext, handler);
|
handler =
|
||||||
|
new WrappingStatusSettingResponseHandler<>(
|
||||||
|
context, parentContext, handler, httpUriRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,6 +276,7 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
public static void methodExit(
|
public static void methodExit(
|
||||||
@Advice.Return Object result,
|
@Advice.Return Object result,
|
||||||
@Advice.Thrown Throwable throwable,
|
@Advice.Thrown Throwable throwable,
|
||||||
|
@Advice.Local("otelHttpUriRequest") HttpUriRequest httpUriRequest,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@Advice.Local("otelScope") Scope scope) {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
|
@ -272,7 +284,7 @@ public class ApacheHttpClientInstrumentationModule extends InstrumentationModule
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.close();
|
scope.close();
|
||||||
ApacheHttpClientHelper.doMethodExit(context, result, throwable);
|
ApacheHttpClientHelper.doMethodExit(context, httpUriRequest, result, throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpAttributesExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor;
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
|
||||||
|
public final class ApacheHttpClientInstrumenters {
|
||||||
|
private static final String INSTRUMENTATION_NAME =
|
||||||
|
"io.opentelemetry.javaagent.apache-httpclient-4.0";
|
||||||
|
|
||||||
|
private static final Instrumenter<HttpUriRequest, HttpResponse> INSTRUMENTER;
|
||||||
|
|
||||||
|
static {
|
||||||
|
HttpAttributesExtractor<HttpUriRequest, HttpResponse> httpAttributesExtractor =
|
||||||
|
new ApacheHttpClientHttpAttributesExtractor();
|
||||||
|
SpanNameExtractor<? super HttpUriRequest> spanNameExtractor =
|
||||||
|
HttpSpanNameExtractor.create(httpAttributesExtractor);
|
||||||
|
SpanStatusExtractor<? super HttpUriRequest, ? super HttpResponse> spanStatusExtractor =
|
||||||
|
HttpSpanStatusExtractor.create(httpAttributesExtractor);
|
||||||
|
|
||||||
|
INSTRUMENTER =
|
||||||
|
Instrumenter.<HttpUriRequest, HttpResponse>newBuilder(
|
||||||
|
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, spanNameExtractor)
|
||||||
|
.setSpanStatusExtractor(spanStatusExtractor)
|
||||||
|
.addAttributesExtractor(httpAttributesExtractor)
|
||||||
|
.addAttributesExtractor(new ApacheHttpClientNetAttributesExtractor())
|
||||||
|
.newClientInstrumenter(HttpHeaderSetter.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Instrumenter<HttpUriRequest, HttpResponse> instrumenter() {
|
||||||
|
return INSTRUMENTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApacheHttpClientInstrumenters() {}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
|
|
||||||
|
import io.opentelemetry.instrumentation.api.instrumenter.net.NetAttributesExtractor;
|
||||||
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||||
|
import java.net.URI;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
|
final class ApacheHttpClientNetAttributesExtractor
|
||||||
|
extends NetAttributesExtractor<HttpUriRequest, HttpResponse> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String transport(HttpUriRequest request) {
|
||||||
|
return SemanticAttributes.NetTransportValues.IP_TCP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable String peerName(HttpUriRequest request, @Nullable HttpResponse response) {
|
||||||
|
return request.getURI().getHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer peerPort(HttpUriRequest request, @Nullable HttpResponse response) {
|
||||||
|
URI uri = request.getURI();
|
||||||
|
int port = uri.getPort();
|
||||||
|
if (port != -1) {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
switch (uri.getScheme()) {
|
||||||
|
case "http":
|
||||||
|
return 80;
|
||||||
|
case "https":
|
||||||
|
return 443;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable String peerIp(HttpUriRequest request, @Nullable HttpResponse response) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.HttpHeadersInjectAdapter.SETTER;
|
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
|
||||||
import io.opentelemetry.context.propagation.TextMapSetter;
|
|
||||||
import io.opentelemetry.instrumentation.api.tracer.HttpClientTracer;
|
|
||||||
import io.opentelemetry.instrumentation.api.tracer.net.NetPeerAttributes;
|
|
||||||
import java.net.URI;
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpMessage;
|
|
||||||
import org.apache.http.HttpRequest;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
public class ApacheHttpClientTracer
|
|
||||||
extends HttpClientTracer<HttpUriRequest, HttpUriRequest, HttpResponse> {
|
|
||||||
|
|
||||||
private static final ApacheHttpClientTracer TRACER = new ApacheHttpClientTracer();
|
|
||||||
|
|
||||||
private ApacheHttpClientTracer() {
|
|
||||||
super(NetPeerAttributes.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ApacheHttpClientTracer tracer() {
|
|
||||||
return TRACER;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context startSpan(Context parentContext, HttpHost host, HttpRequest request) {
|
|
||||||
HttpUriRequest httpUriRequest;
|
|
||||||
if (request instanceof HttpUriRequest) {
|
|
||||||
httpUriRequest = (HttpUriRequest) request;
|
|
||||||
} else {
|
|
||||||
httpUriRequest = new HostAndRequestAsHttpUriRequest(host, request);
|
|
||||||
}
|
|
||||||
return startSpan(parentContext, httpUriRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Context startSpan(Context parentContext, HttpUriRequest request) {
|
|
||||||
return startSpan(parentContext, request, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String method(HttpUriRequest httpRequest) {
|
|
||||||
return httpRequest.getMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected String flavor(HttpUriRequest httpUriRequest) {
|
|
||||||
return httpUriRequest.getProtocolVersion().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected URI url(HttpUriRequest request) {
|
|
||||||
return request.getURI();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Integer status(HttpResponse httpResponse) {
|
|
||||||
return httpResponse.getStatusLine().getStatusCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String requestHeader(HttpUriRequest request, String name) {
|
|
||||||
return header(request, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String responseHeader(HttpResponse response, String name) {
|
|
||||||
return header(response, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected TextMapSetter<HttpUriRequest> getSetter() {
|
|
||||||
return SETTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String header(HttpMessage message, String name) {
|
|
||||||
Header header = message.getFirstHeader(name);
|
|
||||||
return header != null ? header.getValue() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getInstrumentationName() {
|
|
||||||
return "io.opentelemetry.javaagent.apache-httpclient-4.0";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,7 +15,8 @@ import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.message.AbstractHttpMessage;
|
import org.apache.http.message.AbstractHttpMessage;
|
||||||
|
|
||||||
/** Wraps HttpHost and HttpRequest into a HttpUriRequest for tracers and injectors. */
|
/** Wraps HttpHost and HttpRequest into a HttpUriRequest for tracers and injectors. */
|
||||||
public class HostAndRequestAsHttpUriRequest extends AbstractHttpMessage implements HttpUriRequest {
|
public final class HostAndRequestAsHttpUriRequest extends AbstractHttpMessage
|
||||||
|
implements HttpUriRequest {
|
||||||
|
|
||||||
private final String method;
|
private final String method;
|
||||||
private final RequestLine requestLine;
|
private final RequestLine requestLine;
|
||||||
|
@ -74,8 +75,4 @@ public class HostAndRequestAsHttpUriRequest extends AbstractHttpMessage implemen
|
||||||
public java.net.URI getURI() {
|
public java.net.URI getURI() {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpRequest getActualRequest() {
|
|
||||||
return actualRequest;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,8 @@ package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
import io.opentelemetry.context.propagation.TextMapSetter;
|
import io.opentelemetry.context.propagation.TextMapSetter;
|
||||||
import org.apache.http.client.methods.HttpUriRequest;
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
|
||||||
class HttpHeadersInjectAdapter implements TextMapSetter<HttpUriRequest> {
|
enum HttpHeaderSetter implements TextMapSetter<HttpUriRequest> {
|
||||||
|
INSTANCE;
|
||||||
public static final HttpHeadersInjectAdapter SETTER = new HttpHeadersInjectAdapter();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(HttpUriRequest carrier, String key, String value) {
|
public void set(HttpUriRequest carrier, String key, String value) {
|
|
@ -5,29 +5,35 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
package io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0;
|
||||||
|
|
||||||
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientTracer.tracer;
|
import static io.opentelemetry.javaagent.instrumentation.apachehttpclient.v4_0.ApacheHttpClientInstrumenters.instrumenter;
|
||||||
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
import io.opentelemetry.context.Scope;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.ResponseHandler;
|
import org.apache.http.client.ResponseHandler;
|
||||||
|
import org.apache.http.client.methods.HttpUriRequest;
|
||||||
|
|
||||||
public class WrappingStatusSettingResponseHandler<T> implements ResponseHandler<T> {
|
public final class WrappingStatusSettingResponseHandler<T> implements ResponseHandler<T> {
|
||||||
final Context context;
|
private final Context context;
|
||||||
final Context parentContext;
|
private final Context parentContext;
|
||||||
final ResponseHandler<T> handler;
|
private final ResponseHandler<T> handler;
|
||||||
|
private final HttpUriRequest httpUriRequest;
|
||||||
|
|
||||||
public WrappingStatusSettingResponseHandler(
|
public WrappingStatusSettingResponseHandler(
|
||||||
Context context, Context parentContext, ResponseHandler<T> handler) {
|
Context context,
|
||||||
|
Context parentContext,
|
||||||
|
ResponseHandler<T> handler,
|
||||||
|
HttpUriRequest httpUriRequest) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.parentContext = parentContext;
|
this.parentContext = parentContext;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
|
this.httpUriRequest = httpUriRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T handleResponse(HttpResponse response) throws IOException {
|
public T handleResponse(HttpResponse response) throws IOException {
|
||||||
tracer().end(context, response);
|
instrumenter().end(context, httpUriRequest, response, null);
|
||||||
// ending the span before executing the callback handler (and scoping the callback handler to
|
// ending the span before executing the callback handler (and scoping the callback handler to
|
||||||
// the parent context), even though we are inside of a synchronous http client callback
|
// the parent context), even though we are inside of a synchronous http client callback
|
||||||
// underneath HttpClient.execute(..), in order to not attribute other CLIENT span timings that
|
// underneath HttpClient.execute(..), in order to not attribute other CLIENT span timings that
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import io.opentelemetry.api.common.AttributeKey
|
||||||
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
import io.opentelemetry.instrumentation.test.AgentTestTrait
|
||||||
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
import io.opentelemetry.instrumentation.test.base.HttpClientTest
|
||||||
|
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import org.apache.http.HttpHost
|
import org.apache.http.HttpHost
|
||||||
import org.apache.http.HttpRequest
|
import org.apache.http.HttpRequest
|
||||||
|
@ -40,6 +42,15 @@ abstract class ApacheHttpClientTest<T extends HttpRequest> extends HttpClientTes
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
List<AttributeKey<?>> extraAttributes() {
|
||||||
|
[
|
||||||
|
SemanticAttributes.HTTP_SCHEME,
|
||||||
|
SemanticAttributes.HTTP_SCHEME,
|
||||||
|
SemanticAttributes.HTTP_TARGET,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
// compilation fails with @Override annotation on this method (groovy quirk?)
|
// compilation fails with @Override annotation on this method (groovy quirk?)
|
||||||
int sendRequest(T request, String method, URI uri, Map<String, String> headers) {
|
int sendRequest(T request, String method, URI uri, Map<String, String> headers) {
|
||||||
def response = executeRequest(request, uri)
|
def response = executeRequest(request, uri)
|
||||||
|
|
Loading…
Reference in New Issue