indy instrumentation - leftovers migration (#13074)
This commit is contained in:
parent
dc8338c013
commit
ca3c685c3c
|
@ -1,20 +0,0 @@
|
||||||
plugins {
|
|
||||||
id("otel.javaagent-instrumentation")
|
|
||||||
}
|
|
||||||
|
|
||||||
// We cannot use otelJava { minJavaVersionSupported.set(JavaVersion.VERSION_1_9) } because compiler
|
|
||||||
// will fail with -Xlint without providing an error message.
|
|
||||||
// We cannot use "--release" javac option because that will forbid calling methods added in jdk 9.
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
toolchain {
|
|
||||||
languageVersion.set(null as JavaLanguageVersion?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
withType<JavaCompile>().configureEach {
|
|
||||||
options.release.set(null as Int?)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.internal.lambda;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
import java.lang.instrument.IllegalClassFormatException;
|
|
||||||
|
|
||||||
/** Helper class for transforming lambda class bytes using java9 api. */
|
|
||||||
public final class Java9LambdaTransformer {
|
|
||||||
|
|
||||||
private Java9LambdaTransformer() {}
|
|
||||||
|
|
||||||
public static byte[] transform(
|
|
||||||
ClassFileTransformer transformer,
|
|
||||||
byte[] classBytes,
|
|
||||||
String slashClassName,
|
|
||||||
Class<?> targetClass)
|
|
||||||
throws IllegalClassFormatException {
|
|
||||||
return transformer.transform(
|
|
||||||
targetClass.getModule(),
|
|
||||||
targetClass.getClassLoader(),
|
|
||||||
slashClassName,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
classBytes);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,7 +4,6 @@ plugins {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(project(":javaagent-bootstrap"))
|
compileOnly(project(":javaagent-bootstrap"))
|
||||||
implementation(project(":instrumentation:internal:internal-lambda-java9:javaagent"))
|
|
||||||
|
|
||||||
testImplementation(project(":javaagent-bootstrap"))
|
testImplementation(project(":javaagent-bootstrap"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ public class InnerClassLambdaMetafactoryInstrumentation implements TypeInstrumen
|
||||||
Opcodes.GETFIELD, slashClassName, "targetClass", "Ljava/lang/Class;");
|
Opcodes.GETFIELD, slashClassName, "targetClass", "Ljava/lang/Class;");
|
||||||
mv.visitMethodInsn(
|
mv.visitMethodInsn(
|
||||||
Opcodes.INVOKESTATIC,
|
Opcodes.INVOKESTATIC,
|
||||||
Type.getInternalName(LambdaTransformer.class),
|
Type.getInternalName(LambdaTransformerHelper.class),
|
||||||
"transform",
|
"transform",
|
||||||
"([BLjava/lang/String;Ljava/lang/Class;)[B",
|
"([BLjava/lang/String;Ljava/lang/Class;)[B",
|
||||||
false);
|
false);
|
||||||
|
|
|
@ -10,13 +10,14 @@ import static java.util.Collections.singletonList;
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import java.util.ArrayList;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.bytebuddy.utility.JavaModule;
|
|
||||||
|
|
||||||
@AutoService(InstrumentationModule.class)
|
@AutoService(InstrumentationModule.class)
|
||||||
public class LambdaInstrumentationModule extends InstrumentationModule {
|
public class LambdaInstrumentationModule extends InstrumentationModule
|
||||||
|
implements ExperimentalInstrumentationModule {
|
||||||
public LambdaInstrumentationModule() {
|
public LambdaInstrumentationModule() {
|
||||||
super("internal-lambda");
|
super("internal-lambda");
|
||||||
}
|
}
|
||||||
|
@ -28,21 +29,16 @@ public class LambdaInstrumentationModule extends InstrumentationModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isIndyModule() {
|
public List<String> injectedClassNames() {
|
||||||
return false;
|
return Collections.singletonList(
|
||||||
|
"io.opentelemetry.javaagent.instrumentation.internal.lambda.LambdaTransformerHelper");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAdditionalHelperClassNames() {
|
public List<String> getAdditionalHelperClassNames() {
|
||||||
// this instrumentation uses ASM not ByteBuddy so muzzle doesn't automatically add helper
|
// this instrumentation uses ASM not ByteBuddy so muzzle doesn't automatically add helper
|
||||||
// classes
|
// classes
|
||||||
List<String> classNames = new ArrayList<>();
|
return injectedClassNames();
|
||||||
classNames.add("io.opentelemetry.javaagent.instrumentation.internal.lambda.LambdaTransformer");
|
|
||||||
if (JavaModule.isSupported()) {
|
|
||||||
classNames.add(
|
|
||||||
"io.opentelemetry.javaagent.instrumentation.internal.lambda.Java9LambdaTransformer");
|
|
||||||
}
|
|
||||||
return classNames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.internal.lambda;
|
|
||||||
|
|
||||||
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
|
|
||||||
import io.opentelemetry.javaagent.bootstrap.InjectedClassHelper;
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
|
|
||||||
/** Helper class for transforming lambda class bytes. */
|
|
||||||
public final class LambdaTransformer {
|
|
||||||
private static final boolean IS_JAVA_9 = isJava9();
|
|
||||||
|
|
||||||
private LambdaTransformer() {}
|
|
||||||
|
|
||||||
private static boolean isJava9() {
|
|
||||||
try {
|
|
||||||
Class.forName("java.lang.Module", false, null);
|
|
||||||
return true;
|
|
||||||
} catch (ClassNotFoundException exception) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called from {@code java.lang.invoke.InnerClassLambdaMetafactory} to transform lambda class
|
|
||||||
* bytes.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static byte[] transform(byte[] classBytes, String slashClassName, Class<?> targetClass) {
|
|
||||||
// Skip transforming lambdas of injected helper classes.
|
|
||||||
if (InjectedClassHelper.isHelperClass(targetClass)) {
|
|
||||||
return classBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassFileTransformer transformer = ClassFileTransformerHolder.getClassFileTransformer();
|
|
||||||
if (transformer != null) {
|
|
||||||
try {
|
|
||||||
byte[] result;
|
|
||||||
if (IS_JAVA_9) {
|
|
||||||
result =
|
|
||||||
Java9LambdaTransformer.transform(
|
|
||||||
transformer, classBytes, slashClassName, targetClass);
|
|
||||||
} else {
|
|
||||||
result =
|
|
||||||
transformer.transform(
|
|
||||||
targetClass.getClassLoader(), slashClassName, null, null, classBytes);
|
|
||||||
}
|
|
||||||
if (result != null) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} catch (Throwable throwable) {
|
|
||||||
// sun.instrument.TransformerManager catches Throwable from ClassFileTransformer and ignores
|
|
||||||
// it, we do the same.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return classBytes;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.instrumentation.internal.lambda;
|
||||||
|
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.InjectedClassHelper;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.LambdaTransformer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.LambdaTransformerHolder;
|
||||||
|
|
||||||
|
/** Helper class for transforming lambda class bytes. */
|
||||||
|
public final class LambdaTransformerHelper {
|
||||||
|
|
||||||
|
private LambdaTransformerHelper() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from {@code java.lang.invoke.InnerClassLambdaMetafactory} to transform lambda class
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static byte[] transform(byte[] classBytes, String slashClassName, Class<?> targetClass) {
|
||||||
|
// Skip transforming lambdas of injected helper classes.
|
||||||
|
if (InjectedClassHelper.isHelperClass(targetClass)) {
|
||||||
|
return classBytes;
|
||||||
|
}
|
||||||
|
LambdaTransformer transformer = LambdaTransformerHolder.getLambdaTransformer();
|
||||||
|
if (transformer == null) {
|
||||||
|
return classBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] result = transformer.transform(slashClassName, targetClass, classBytes);
|
||||||
|
if (result != null) {
|
||||||
|
classBytes = result;
|
||||||
|
}
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
// sun.instrument.TransformerManager catches Throwable from ClassFileTransformer and ignores
|
||||||
|
// it, we do the same.
|
||||||
|
}
|
||||||
|
return classBytes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,12 +15,20 @@ import io.opentelemetry.instrumentation.api.util.VirtualField;
|
||||||
import kotlin.coroutines.Continuation;
|
import kotlin.coroutines.Continuation;
|
||||||
import kotlin.coroutines.intrinsics.IntrinsicsKt;
|
import kotlin.coroutines.intrinsics.IntrinsicsKt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumentation helper that is called through bytecode instrumentation. When using invokedynamic
|
||||||
|
* instrumentation this class is called through an injected proxy, and thus it should not pull any
|
||||||
|
* other class references than the ones that are already present in the target classloader or the
|
||||||
|
* bootstrap classloader. This is why the {@link MethodRequest} class is here passed as an {@link
|
||||||
|
* Object} as it allows to avoid having to inject extra classes in the target classloader
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused") // methods calls injected through bytecode instrumentation
|
||||||
public final class AnnotationInstrumentationHelper {
|
public final class AnnotationInstrumentationHelper {
|
||||||
|
|
||||||
private static final VirtualField<Continuation<?>, Context> contextField =
|
private static final VirtualField<Continuation<?>, Context> contextField =
|
||||||
VirtualField.find(Continuation.class, Context.class);
|
VirtualField.find(Continuation.class, Context.class);
|
||||||
|
|
||||||
public static MethodRequest createMethodRequest(
|
public static Object createMethodRequest(
|
||||||
Class<?> declaringClass, String methodName, String withSpanValue, String spanKindString) {
|
Class<?> declaringClass, String methodName, String withSpanValue, String spanKindString) {
|
||||||
SpanKind spanKind = SpanKind.INTERNAL;
|
SpanKind spanKind = SpanKind.INTERNAL;
|
||||||
if (spanKindString != null) {
|
if (spanKindString != null) {
|
||||||
|
@ -34,11 +42,10 @@ public final class AnnotationInstrumentationHelper {
|
||||||
return MethodRequest.create(declaringClass, methodName, withSpanValue, spanKind);
|
return MethodRequest.create(declaringClass, methodName, withSpanValue, spanKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Context enterCoroutine(
|
public static Context enterCoroutine(int label, Continuation<?> continuation, Object request) {
|
||||||
int label, Continuation<?> continuation, MethodRequest request) {
|
|
||||||
// label 0 means that coroutine is started, any other label means that coroutine is resumed
|
// label 0 means that coroutine is started, any other label means that coroutine is resumed
|
||||||
if (label == 0) {
|
if (label == 0) {
|
||||||
Context context = instrumenter().start(Context.current(), request);
|
Context context = instrumenter().start(Context.current(), (MethodRequest) request);
|
||||||
// null continuation means that this method is not going to be resumed, and we don't need to
|
// null continuation means that this method is not going to be resumed, and we don't need to
|
||||||
// store the context
|
// store the context
|
||||||
if (continuation != null) {
|
if (continuation != null) {
|
||||||
|
@ -55,18 +62,14 @@ public final class AnnotationInstrumentationHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void exitCoroutine(
|
public static void exitCoroutine(
|
||||||
Object result,
|
Object result, Object request, Continuation<?> continuation, Context context, Scope scope) {
|
||||||
MethodRequest request,
|
|
||||||
Continuation<?> continuation,
|
|
||||||
Context context,
|
|
||||||
Scope scope) {
|
|
||||||
exitCoroutine(null, result, request, continuation, context, scope);
|
exitCoroutine(null, result, request, continuation, context, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void exitCoroutine(
|
public static void exitCoroutine(
|
||||||
Throwable error,
|
Throwable error,
|
||||||
Object result,
|
Object result,
|
||||||
MethodRequest request,
|
Object request,
|
||||||
Continuation<?> continuation,
|
Continuation<?> continuation,
|
||||||
Context context,
|
Context context,
|
||||||
Scope scope) {
|
Scope scope) {
|
||||||
|
@ -78,7 +81,7 @@ public final class AnnotationInstrumentationHelper {
|
||||||
// end the span when this method can not be resumed (coroutine is null) or if it has reached
|
// end the span when this method can not be resumed (coroutine is null) or if it has reached
|
||||||
// final state (returns anything else besides COROUTINE_SUSPENDED)
|
// final state (returns anything else besides COROUTINE_SUSPENDED)
|
||||||
if (continuation == null || result != IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
|
if (continuation == null || result != IntrinsicsKt.getCOROUTINE_SUSPENDED()) {
|
||||||
instrumenter().end(context, request, null, error);
|
instrumenter().end(context, (MethodRequest) request, null, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,16 @@ import static java.util.Collections.singletonList;
|
||||||
import com.google.auto.service.AutoService;
|
import com.google.auto.service.AutoService;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.internal.injection.ClassInjector;
|
||||||
|
import io.opentelemetry.javaagent.extension.instrumentation.internal.injection.InjectionMode;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
/** Instrumentation for methods annotated with {@code WithSpan} annotation. */
|
/** Instrumentation for methods annotated with {@code WithSpan} annotation. */
|
||||||
@AutoService(InstrumentationModule.class)
|
@AutoService(InstrumentationModule.class)
|
||||||
public class AnnotationInstrumentationModule extends InstrumentationModule {
|
public class AnnotationInstrumentationModule extends InstrumentationModule
|
||||||
|
implements ExperimentalInstrumentationModule {
|
||||||
|
|
||||||
public AnnotationInstrumentationModule() {
|
public AnnotationInstrumentationModule() {
|
||||||
super(
|
super(
|
||||||
|
@ -26,12 +30,6 @@ public class AnnotationInstrumentationModule extends InstrumentationModule {
|
||||||
"opentelemetry-instrumentation-annotations");
|
"opentelemetry-instrumentation-annotations");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isIndyModule() {
|
|
||||||
// needs helper classes in the same class loader
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int order() {
|
public int order() {
|
||||||
// Run first to ensure other automatic instrumentation is added after and therefore is executed
|
// Run first to ensure other automatic instrumentation is added after and therefore is executed
|
||||||
|
@ -50,4 +48,17 @@ public class AnnotationInstrumentationModule extends InstrumentationModule {
|
||||||
public List<TypeInstrumentation> typeInstrumentations() {
|
public List<TypeInstrumentation> typeInstrumentations() {
|
||||||
return singletonList(new WithSpanInstrumentation());
|
return singletonList(new WithSpanInstrumentation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectClasses(ClassInjector injector) {
|
||||||
|
// AnnotationInstrumentationHelper is called directly in the instrumented bytecode.
|
||||||
|
//
|
||||||
|
// With invokedynamic instrumentation a proxy class can be used as long as it does not pull
|
||||||
|
// extra types in the method signatures (which would require those types to also be available
|
||||||
|
// in the instrumented code).
|
||||||
|
injector
|
||||||
|
.proxyBuilder(
|
||||||
|
"io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines.instrumentationannotations.AnnotationInstrumentationHelper")
|
||||||
|
.inject(InjectionMode.CLASS_ONLY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
public void visitCode() {
|
public void visitCode() {
|
||||||
super.visitCode();
|
super.visitCode();
|
||||||
// add our local variables after method arguments, this will shift rest of the locals
|
// add our local variables after method arguments, this will shift rest of the locals
|
||||||
requestLocal = newLocal(Type.getType(MethodRequest.class));
|
requestLocal = newLocal(Type.getType(Object.class));
|
||||||
ourContinuationLocal = newLocal(Type.getType(Continuation.class));
|
ourContinuationLocal = newLocal(Type.getType(Continuation.class));
|
||||||
contextLocal = newLocal(Type.getType(Context.class));
|
contextLocal = newLocal(Type.getType(Context.class));
|
||||||
scopeLocal = newLocal(Type.getType(Scope.class));
|
scopeLocal = newLocal(Type.getType(Scope.class));
|
||||||
|
@ -324,7 +324,8 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
// initialize our local variables, start span and open scope
|
// initialize our local variables, start span and open scope
|
||||||
{
|
{
|
||||||
MethodNode temp = new MethodNode();
|
MethodNode temp = new MethodNode();
|
||||||
// insert
|
// insert the following code
|
||||||
|
//
|
||||||
// request =
|
// request =
|
||||||
// AnnotationInstrumentationHelper.createMethodRequest(InstrumentedClass.class,
|
// AnnotationInstrumentationHelper.createMethodRequest(InstrumentedClass.class,
|
||||||
// instrumentedMethodName, withSpanValue, withSpanKind)
|
// instrumentedMethodName, withSpanValue, withSpanKind)
|
||||||
|
@ -360,32 +361,26 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
} else {
|
} else {
|
||||||
temp.visitInsn(Opcodes.ACONST_NULL);
|
temp.visitInsn(Opcodes.ACONST_NULL);
|
||||||
}
|
}
|
||||||
temp.visitMethodInsn(
|
visitInvokeHelperMethod(
|
||||||
Opcodes.INVOKESTATIC,
|
temp,
|
||||||
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
|
||||||
"createMethodRequest",
|
"createMethodRequest",
|
||||||
"(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)"
|
"(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
|
||||||
+ Type.getDescriptor(MethodRequest.class),
|
|
||||||
false);
|
|
||||||
temp.visitInsn(Opcodes.DUP);
|
temp.visitInsn(Opcodes.DUP);
|
||||||
temp.visitVarInsn(Opcodes.ASTORE, requestLocal);
|
temp.visitVarInsn(Opcodes.ASTORE, requestLocal);
|
||||||
temp.visitMethodInsn(
|
visitInvokeHelperMethod(
|
||||||
Opcodes.INVOKESTATIC,
|
temp,
|
||||||
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
|
||||||
"enterCoroutine",
|
"enterCoroutine",
|
||||||
"(ILkotlin/coroutines/Continuation;"
|
"(ILkotlin/coroutines/Continuation;Ljava/lang/Object;)"
|
||||||
+ Type.getDescriptor(MethodRequest.class)
|
+ Type.getDescriptor(Context.class));
|
||||||
+ ")"
|
|
||||||
+ Type.getDescriptor(Context.class),
|
|
||||||
false);
|
|
||||||
temp.visitInsn(Opcodes.DUP);
|
temp.visitInsn(Opcodes.DUP);
|
||||||
temp.visitVarInsn(Opcodes.ASTORE, contextLocal);
|
temp.visitVarInsn(Opcodes.ASTORE, contextLocal);
|
||||||
temp.visitMethodInsn(
|
visitInvokeHelperMethod(
|
||||||
Opcodes.INVOKESTATIC,
|
temp,
|
||||||
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
|
||||||
"openScope",
|
"openScope",
|
||||||
"(" + Type.getDescriptor(Context.class) + ")" + Type.getDescriptor(Scope.class),
|
"("
|
||||||
false);
|
+ Type.getDescriptor(Context.class)
|
||||||
|
+ ")"
|
||||||
|
+ Type.getDescriptor(Scope.class));
|
||||||
temp.visitVarInsn(Opcodes.ASTORE, scopeLocal);
|
temp.visitVarInsn(Opcodes.ASTORE, scopeLocal);
|
||||||
// @SpanAttribute handling
|
// @SpanAttribute handling
|
||||||
for (Parameter parameter : annotatedParameters) {
|
for (Parameter parameter : annotatedParameters) {
|
||||||
|
@ -396,14 +391,12 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
boolean primitive =
|
boolean primitive =
|
||||||
parameter.type.getSort() != Type.ARRAY
|
parameter.type.getSort() != Type.ARRAY
|
||||||
&& parameter.type.getSort() != Type.OBJECT;
|
&& parameter.type.getSort() != Type.OBJECT;
|
||||||
temp.visitMethodInsn(
|
visitInvokeHelperMethod(
|
||||||
Opcodes.INVOKESTATIC,
|
temp,
|
||||||
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
|
||||||
"setSpanAttribute",
|
"setSpanAttribute",
|
||||||
"(ILjava/lang/String;"
|
"(ILjava/lang/String;"
|
||||||
+ (primitive ? parameter.type.getDescriptor() : "Ljava/lang/Object;")
|
+ (primitive ? parameter.type.getDescriptor() : "Ljava/lang/Object;")
|
||||||
+ ")V",
|
+ ")V");
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
// pop label
|
// pop label
|
||||||
temp.visitInsn(Opcodes.POP);
|
temp.visitInsn(Opcodes.POP);
|
||||||
|
@ -446,7 +439,7 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
// in this handler we are using only the locals we added, we don't care about method
|
// in this handler we are using only the locals we added, we don't care about method
|
||||||
// arguments and this, so we don't list them in the stack frame
|
// arguments and this, so we don't list them in the stack frame
|
||||||
Arrays.fill(locals, Opcodes.TOP);
|
Arrays.fill(locals, Opcodes.TOP);
|
||||||
locals[requestLocal] = Type.getInternalName(MethodRequest.class);
|
locals[requestLocal] = Type.getInternalName(Object.class);
|
||||||
locals[ourContinuationLocal] = Type.getInternalName(Continuation.class);
|
locals[ourContinuationLocal] = Type.getInternalName(Continuation.class);
|
||||||
locals[contextLocal] = Type.getInternalName(Context.class);
|
locals[contextLocal] = Type.getInternalName(Context.class);
|
||||||
locals[scopeLocal] = Type.getInternalName(Scope.class);
|
locals[scopeLocal] = Type.getInternalName(Scope.class);
|
||||||
|
@ -463,17 +456,15 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
temp.visitVarInsn(Opcodes.ALOAD, ourContinuationLocal);
|
temp.visitVarInsn(Opcodes.ALOAD, ourContinuationLocal);
|
||||||
temp.visitVarInsn(Opcodes.ALOAD, contextLocal);
|
temp.visitVarInsn(Opcodes.ALOAD, contextLocal);
|
||||||
temp.visitVarInsn(Opcodes.ALOAD, scopeLocal);
|
temp.visitVarInsn(Opcodes.ALOAD, scopeLocal);
|
||||||
temp.visitMethodInsn(
|
visitInvokeHelperMethod(
|
||||||
Opcodes.INVOKESTATIC,
|
temp,
|
||||||
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
|
||||||
"exitCoroutine",
|
"exitCoroutine",
|
||||||
"(Ljava/lang/Throwable;Ljava/lang/Object;"
|
"(Ljava/lang/Throwable;Ljava/lang/Object;"
|
||||||
+ Type.getDescriptor(MethodRequest.class)
|
+ "Ljava/lang/Object;"
|
||||||
+ Type.getDescriptor(Continuation.class)
|
+ Type.getDescriptor(Continuation.class)
|
||||||
+ Type.getDescriptor(Context.class)
|
+ Type.getDescriptor(Context.class)
|
||||||
+ Type.getDescriptor(Scope.class)
|
+ Type.getDescriptor(Scope.class)
|
||||||
+ ")V",
|
+ ")V");
|
||||||
false);
|
|
||||||
|
|
||||||
// rethrow the exception
|
// rethrow the exception
|
||||||
temp.visitInsn(Opcodes.ATHROW);
|
temp.visitInsn(Opcodes.ATHROW);
|
||||||
|
@ -498,17 +489,15 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
temp.visitVarInsn(Opcodes.ALOAD, ourContinuationLocal);
|
temp.visitVarInsn(Opcodes.ALOAD, ourContinuationLocal);
|
||||||
temp.visitVarInsn(Opcodes.ALOAD, contextLocal);
|
temp.visitVarInsn(Opcodes.ALOAD, contextLocal);
|
||||||
temp.visitVarInsn(Opcodes.ALOAD, scopeLocal);
|
temp.visitVarInsn(Opcodes.ALOAD, scopeLocal);
|
||||||
temp.visitMethodInsn(
|
visitInvokeHelperMethod(
|
||||||
Opcodes.INVOKESTATIC,
|
temp,
|
||||||
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
|
||||||
"exitCoroutine",
|
"exitCoroutine",
|
||||||
"(Ljava/lang/Object;"
|
"(Ljava/lang/Object;"
|
||||||
+ Type.getDescriptor(MethodRequest.class)
|
+ "Ljava/lang/Object;"
|
||||||
+ Type.getDescriptor(Continuation.class)
|
+ Type.getDescriptor(Continuation.class)
|
||||||
+ Type.getDescriptor(Context.class)
|
+ Type.getDescriptor(Context.class)
|
||||||
+ Type.getDescriptor(Scope.class)
|
+ Type.getDescriptor(Scope.class)
|
||||||
+ ")V",
|
+ ")V");
|
||||||
false);
|
|
||||||
methodNode.instructions.insertBefore(instruction, temp.instructions);
|
methodNode.instructions.insertBefore(instruction, temp.instructions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -519,5 +508,15 @@ class WithSpanInstrumentation implements TypeInstrumentation {
|
||||||
|
|
||||||
return generatorAdapter;
|
return generatorAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void visitInvokeHelperMethod(
|
||||||
|
MethodNode methodNode, String methodName, String descriptor) {
|
||||||
|
methodNode.visitMethodInsn(
|
||||||
|
Opcodes.INVOKESTATIC,
|
||||||
|
Type.getInternalName(AnnotationInstrumentationHelper.class),
|
||||||
|
methodName,
|
||||||
|
descriptor,
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.bootstrap;
|
|
||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holder for {@link ClassFileTransformer} used by the instrumentation. Calling transform on this
|
|
||||||
* class file transformer processes given bytes the same way as they would be processed during
|
|
||||||
* loading of the class.
|
|
||||||
*/
|
|
||||||
public final class ClassFileTransformerHolder {
|
|
||||||
|
|
||||||
private static volatile ClassFileTransformer classFileTransformer;
|
|
||||||
|
|
||||||
public static ClassFileTransformer getClassFileTransformer() {
|
|
||||||
return classFileTransformer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setClassFileTransformer(ClassFileTransformer transformer) {
|
|
||||||
classFileTransformer = transformer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassFileTransformerHolder() {}
|
|
||||||
}
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.bootstrap;
|
||||||
|
|
||||||
|
import java.lang.instrument.IllegalClassFormatException;
|
||||||
|
|
||||||
|
/** Transformer for lambda bytecode */
|
||||||
|
public interface LambdaTransformer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms lambda bytecode for instrumentation
|
||||||
|
*
|
||||||
|
* @param className class name in JVM format with slashes
|
||||||
|
* @param targetClass target class, must not be {@literal null}
|
||||||
|
* @param classfileBuffer target class bytecode
|
||||||
|
* @return instrumented lambda bytecode
|
||||||
|
* @throws IllegalClassFormatException if bytecode is invalid
|
||||||
|
*/
|
||||||
|
byte[] transform(String className, Class<?> targetClass, byte[] classfileBuffer)
|
||||||
|
throws IllegalClassFormatException;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.bootstrap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holder for {@link LambdaTransformer} used by the instrumentation. Calling transform on this
|
||||||
|
* transformer processes given bytes the same way as they would be processed during loading of the
|
||||||
|
* class.
|
||||||
|
*/
|
||||||
|
public final class LambdaTransformerHolder {
|
||||||
|
|
||||||
|
private static volatile LambdaTransformer lambdaTransformer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get lambda transformer
|
||||||
|
*
|
||||||
|
* @return class transformer for defining lambdas
|
||||||
|
*/
|
||||||
|
public static LambdaTransformer getLambdaTransformer() {
|
||||||
|
return lambdaTransformer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set lambda transformer
|
||||||
|
*
|
||||||
|
* @param transformer transformer
|
||||||
|
*/
|
||||||
|
public static void setLambdaTransformer(LambdaTransformer transformer) {
|
||||||
|
lambdaTransformer = transformer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaTransformerHolder() {}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.tooling;
|
||||||
|
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.LambdaTransformer;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.IllegalClassFormatException;
|
||||||
|
|
||||||
|
/** lambda transformer with java9 jpms module compatibility */
|
||||||
|
public class Java9LambdaTransformer implements LambdaTransformer {
|
||||||
|
|
||||||
|
private final ClassFileTransformer delegate;
|
||||||
|
|
||||||
|
public Java9LambdaTransformer(ClassFileTransformer delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] transform(String className, Class<?> targetClass, byte[] classfileBuffer)
|
||||||
|
throws IllegalClassFormatException {
|
||||||
|
|
||||||
|
// lambda instrumentation happens only when the lambda is being defined, so the targetClass
|
||||||
|
// argument should not be passed to the transformer otherwise we get a partial instrumentation,
|
||||||
|
// for example virtual fields are not properly applied
|
||||||
|
return delegate.transform(
|
||||||
|
targetClass.getModule(),
|
||||||
|
targetClass.getClassLoader(),
|
||||||
|
className,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
classfileBuffer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,9 +21,10 @@ import io.opentelemetry.context.Scope;
|
||||||
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
|
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
|
||||||
import io.opentelemetry.javaagent.bootstrap.AgentClassLoader;
|
import io.opentelemetry.javaagent.bootstrap.AgentClassLoader;
|
||||||
import io.opentelemetry.javaagent.bootstrap.BootstrapPackagePrefixesHolder;
|
import io.opentelemetry.javaagent.bootstrap.BootstrapPackagePrefixesHolder;
|
||||||
import io.opentelemetry.javaagent.bootstrap.ClassFileTransformerHolder;
|
|
||||||
import io.opentelemetry.javaagent.bootstrap.DefineClassHelper;
|
import io.opentelemetry.javaagent.bootstrap.DefineClassHelper;
|
||||||
import io.opentelemetry.javaagent.bootstrap.InstrumentedTaskClasses;
|
import io.opentelemetry.javaagent.bootstrap.InstrumentedTaskClasses;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.LambdaTransformer;
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.LambdaTransformerHolder;
|
||||||
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizer;
|
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizer;
|
||||||
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
|
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseCustomizerHolder;
|
||||||
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
|
import io.opentelemetry.javaagent.bootstrap.http.HttpServerResponseMutator;
|
||||||
|
@ -48,6 +49,7 @@ import io.opentelemetry.javaagent.tooling.util.Trie;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
|
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -63,7 +65,6 @@ import javax.annotation.Nullable;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
import net.bytebuddy.agent.builder.AgentBuilderUtil;
|
import net.bytebuddy.agent.builder.AgentBuilderUtil;
|
||||||
import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
|
|
||||||
import net.bytebuddy.description.type.TypeDefinition;
|
import net.bytebuddy.description.type.TypeDefinition;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
@ -199,9 +200,18 @@ public class AgentInstaller {
|
||||||
logger.log(FINE, "Installed {0} extension(s)", numberOfLoadedExtensions);
|
logger.log(FINE, "Installed {0} extension(s)", numberOfLoadedExtensions);
|
||||||
|
|
||||||
agentBuilder = AgentBuilderUtil.optimize(agentBuilder);
|
agentBuilder = AgentBuilderUtil.optimize(agentBuilder);
|
||||||
ResettableClassFileTransformer resettableClassFileTransformer = agentBuilder.installOn(inst);
|
ClassFileTransformer transformer = agentBuilder.installOn(inst);
|
||||||
|
LambdaTransformer lambdaTransformer;
|
||||||
|
if (JavaModule.isSupported()) {
|
||||||
|
// wrapping in a JPMS compliant implementation
|
||||||
|
lambdaTransformer = new Java9LambdaTransformer(transformer);
|
||||||
|
} else {
|
||||||
|
// wrapping in a java 8 compliant transformer
|
||||||
|
lambdaTransformer = new Java8LambdaTransformer(transformer);
|
||||||
|
}
|
||||||
|
LambdaTransformerHolder.setLambdaTransformer(lambdaTransformer);
|
||||||
|
|
||||||
instrumentationInstalled = true;
|
instrumentationInstalled = true;
|
||||||
ClassFileTransformerHolder.setClassFileTransformer(resettableClassFileTransformer);
|
|
||||||
|
|
||||||
addHttpServerResponseCustomizers(extensionClassLoader);
|
addHttpServerResponseCustomizers(extensionClassLoader);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.javaagent.tooling;
|
||||||
|
|
||||||
|
import io.opentelemetry.javaagent.bootstrap.LambdaTransformer;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.IllegalClassFormatException;
|
||||||
|
|
||||||
|
/** lambda transformer for java < 9 without jpms modules support */
|
||||||
|
public class Java8LambdaTransformer implements LambdaTransformer {
|
||||||
|
|
||||||
|
private final ClassFileTransformer delegate;
|
||||||
|
|
||||||
|
public Java8LambdaTransformer(ClassFileTransformer delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] transform(String className, Class<?> targetClass, byte[] classfileBuffer)
|
||||||
|
throws IllegalClassFormatException {
|
||||||
|
|
||||||
|
// lambda instrumentation happens only when the lambda is being defined, so the targetClass
|
||||||
|
// argument should not be passed to the transformer otherwise we get a partial instrumentation,
|
||||||
|
// for example virtual fields are not properly applied
|
||||||
|
return delegate.transform(targetClass.getClassLoader(), className, null, null, classfileBuffer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -259,7 +259,6 @@ include(":instrumentation:internal:internal-class-loader:javaagent")
|
||||||
include(":instrumentation:internal:internal-class-loader:javaagent-integration-tests")
|
include(":instrumentation:internal:internal-class-loader:javaagent-integration-tests")
|
||||||
include(":instrumentation:internal:internal-eclipse-osgi-3.6:javaagent")
|
include(":instrumentation:internal:internal-eclipse-osgi-3.6:javaagent")
|
||||||
include(":instrumentation:internal:internal-lambda:javaagent")
|
include(":instrumentation:internal:internal-lambda:javaagent")
|
||||||
include(":instrumentation:internal:internal-lambda-java9:javaagent")
|
|
||||||
include(":instrumentation:internal:internal-reflection:javaagent")
|
include(":instrumentation:internal:internal-reflection:javaagent")
|
||||||
include(":instrumentation:internal:internal-reflection:javaagent-integration-tests")
|
include(":instrumentation:internal:internal-reflection:javaagent-integration-tests")
|
||||||
include(":instrumentation:internal:internal-url-class-loader:javaagent")
|
include(":instrumentation:internal:internal-url-class-loader:javaagent")
|
||||||
|
|
|
@ -52,7 +52,6 @@ tasks {
|
||||||
includeTestsMatching("InstrumentOldBytecode")
|
includeTestsMatching("InstrumentOldBytecode")
|
||||||
}
|
}
|
||||||
include("**/InstrumentOldBytecode.*")
|
include("**/InstrumentOldBytecode.*")
|
||||||
jvmArgs("-Dotel.instrumentation.inline-ibm-resource-level.enabled=false")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val testInlineModuleOldBytecodeInstrumentation by registering(Test::class) {
|
val testInlineModuleOldBytecodeInstrumentation by registering(Test::class) {
|
||||||
|
@ -60,7 +59,6 @@ tasks {
|
||||||
includeTestsMatching("InstrumentOldBytecode")
|
includeTestsMatching("InstrumentOldBytecode")
|
||||||
}
|
}
|
||||||
include("**/InstrumentOldBytecode.*")
|
include("**/InstrumentOldBytecode.*")
|
||||||
jvmArgs("-Dotel.instrumentation.indy-ibm-resource-level.enabled=false")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|
|
@ -11,13 +11,13 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@AutoService(InstrumentationModule.class)
|
@AutoService(InstrumentationModule.class)
|
||||||
public class InlineIbmResourceLevelInstrumentationModule extends InstrumentationModule {
|
public class IbmResourceLevelInstrumentationModule extends InstrumentationModule {
|
||||||
public InlineIbmResourceLevelInstrumentationModule() {
|
public IbmResourceLevelInstrumentationModule() {
|
||||||
super("inline-ibm-resource-level");
|
super("ibm-resource-level");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TypeInstrumentation> typeInstrumentations() {
|
public List<TypeInstrumentation> typeInstrumentations() {
|
||||||
return singletonList(new InlineResourceLevelInstrumentation());
|
return singletonList(new ResourceLevelInstrumentation());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
|
||||||
|
|
||||||
import com.google.auto.service.AutoService;
|
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@AutoService(InstrumentationModule.class)
|
|
||||||
public class IndyIbmResourceLevelInstrumentationModule extends InstrumentationModule {
|
|
||||||
public IndyIbmResourceLevelInstrumentationModule() {
|
|
||||||
super("indy-ibm-resource-level");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isIndyModule() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<TypeInstrumentation> typeInstrumentations() {
|
|
||||||
return singletonList(new IndyResourceLevelInstrumentation());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright The OpenTelemetry Authors
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class InlineResourceLevelInstrumentation implements TypeInstrumentation {
|
|
||||||
@Override
|
|
||||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
|
||||||
return named("com.ibm.as400.resource.ResourceLevel");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transform(TypeTransformer transformer) {
|
|
||||||
transformer.applyAdviceToMethod(
|
|
||||||
named("toString"), this.getClass().getName() + "$ToStringAdvice");
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static class ToStringAdvice {
|
|
||||||
@Advice.OnMethodExit(suppress = Throwable.class)
|
|
||||||
static void toStringReplace(@Advice.Return(readOnly = false) String ret) {
|
|
||||||
ret = "instrumented";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,7 +11,7 @@ import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
|
||||||
public class IndyResourceLevelInstrumentation implements TypeInstrumentation {
|
public class ResourceLevelInstrumentation implements TypeInstrumentation {
|
||||||
@Override
|
@Override
|
||||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||||
return named("com.ibm.as400.resource.ResourceLevel");
|
return named("com.ibm.as400.resource.ResourceLevel");
|
||||||
|
@ -25,7 +25,7 @@ public class IndyResourceLevelInstrumentation implements TypeInstrumentation {
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static class ToStringAdvice {
|
public static class ToStringAdvice {
|
||||||
@Advice.OnMethodExit(suppress = Throwable.class, inline = false)
|
@Advice.OnMethodExit(suppress = Throwable.class)
|
||||||
@Advice.AssignReturned.ToReturned
|
@Advice.AssignReturned.ToReturned
|
||||||
public static String toStringReplace() {
|
public static String toStringReplace() {
|
||||||
return "instrumented";
|
return "instrumented";
|
Loading…
Reference in New Issue