Skip to content

Commit

Permalink
chore: move TypeInstrumention into standalone class
Browse files Browse the repository at this point in the history
  • Loading branch information
robododge committed Jun 26, 2021
1 parent 6a52659 commit b50d84b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v9_2;

import static io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientWrapUtil.wrapResponseListeners;
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v9_2.JettyHttpClientSingletons.instrumenter;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
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.jetty.httpclient.v9_2.internal.JettyHttpClient9TracingInterceptor;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import java.util.List;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.eclipse.jetty.client.HttpRequest;
import org.eclipse.jetty.client.api.Response;

public class JettyHttpClient9Instrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.eclipse.jetty.client.HttpClient");
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
isMethod()
.and(named("send"))
.and(takesArgument(0, named("org.eclipse.jetty.client.HttpRequest")))
.and(takesArgument(1, List.class)),
JettyHttpClient9Instrumentation.class.getName() + "$JettyHttpClient9Advice");
}

@SuppressWarnings("unused")
public static class JettyHttpClient9Advice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void addTracingEnter(
@Advice.Argument(value = 0) HttpRequest httpRequest,
@Advice.Argument(value = 1, readOnly = false) List<Response.ResponseListener> listeners,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
Context parentContext = currentContext();
if (!instrumenter().shouldStart(parentContext, httpRequest)) {
return;
}

// First step is to attach the tracer to the Jetty request. Request listeners are wrapped here
JettyHttpClient9TracingInterceptor requestInterceptor =
new JettyHttpClient9TracingInterceptor(parentContext, instrumenter());
requestInterceptor.attachToRequest(httpRequest);

// Second step is to wrap all the important result callback
listeners = wrapResponseListeners(parentContext, listeners);

context = requestInterceptor.getContext();
scope = context.makeCurrent();
}

@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
public static void exitTracingInterceptor(
@Advice.Argument(value = 0) HttpRequest httpRequest,
@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, httpRequest, null, throwable);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,14 @@

package io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v9_2;

import static io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyClientWrapUtil.wrapResponseListeners;
import static io.opentelemetry.javaagent.extension.matcher.ClassLoaderMatcher.hasClassesNamed;
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
import static io.opentelemetry.javaagent.instrumentation.jetty.httpclient.v9_2.JettyHttpClientSingletons.instrumenter;
import static java.util.Collections.singletonList;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.named;

import com.google.auto.service.AutoService;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.jetty.httpclient.v9_2.internal.JettyHttpClient9TracingInterceptor;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import java.util.List;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.eclipse.jetty.client.HttpRequest;
import org.eclipse.jetty.client.api.Response;

@AutoService(InstrumentationModule.class)
public class JettyHttpClient9InstrumentationModule extends InstrumentationModule {
Expand All @@ -44,63 +31,4 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
// AbstractTypedContentProvider showed up in version Jetty Client 9.2 on to 10.x
return hasClassesNamed("org.eclipse.jetty.client.util.AbstractTypedContentProvider");
}

public static class JettyHttpClient9Instrumentation implements TypeInstrumentation {

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.eclipse.jetty.client.HttpClient");
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
isMethod().and(named("send")),
JettyHttpClient9InstrumentationModule.class.getName() + "$JettyHttpClient9Advice");
}
}

public static class JettyHttpClient9Advice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void addTracingEnter(
@Advice.Argument(value = 0) HttpRequest httpRequest,
@Advice.Argument(value = 1, readOnly = false) List<Response.ResponseListener> listeners,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
Context parentContext = currentContext();
if (!instrumenter().shouldStart(parentContext, httpRequest)) {
return;
}

// First step is to attach the tracer to the Jetty request. Request listeners are wrapped here
JettyHttpClient9TracingInterceptor requestInterceptor =
new JettyHttpClient9TracingInterceptor(parentContext, instrumenter());
requestInterceptor.attachToRequest(httpRequest);

// Second step is to wrap all the important result callback
listeners = wrapResponseListeners(parentContext, listeners);

context = requestInterceptor.getContext();
scope = context.makeCurrent();
}

@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
public static void exitTracingInterceptor(
@Advice.Argument(value = 0) HttpRequest httpRequest,
@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, httpRequest, null, throwable);
}
}
}
}

0 comments on commit b50d84b

Please sign in to comment.