-
Notifications
You must be signed in to change notification settings - Fork 969
indy instrumentation - leftovers migration #13074
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 16 commits
c911faa
26e79f9
7f3ae3b
9183992
29c99dd
45ead47
ba30ba8
eb945b8
eba7e20
7a1cbc7
590f86e
a8cbb24
403caaa
506cc62
da1c13d
c4350d0
1d54a14
03aa810
2ed4e96
77a4f00
d9cd13f
5e2ef89
20856e3
a38763f
b77428c
bc785b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,21 +11,11 @@ | |
|
||
/** 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 | ||
* Called from {@code java.lang.invoke.InnerClassLambdaMetaFactory} to transform lambda class | ||
* bytes. | ||
*/ | ||
@SuppressWarnings("unused") | ||
|
@@ -34,29 +24,25 @@ public static byte[] transform(byte[] classBytes, String slashClassName, Class<? | |
if (InjectedClassHelper.isHelperClass(targetClass)) { | ||
return classBytes; | ||
} | ||
ClassFileTransformer transformer = ClassFileTransformerHolder.getLambdaClassFileTransformer(); | ||
if (transformer == null) { | ||
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. | ||
try { | ||
// The 'targetClass' needs to be non-null as it is used in Java9LambdaClassFileTransformer | ||
// to get a reference to the jpms module. However, a null value must be passed to the | ||
// underlying transformer as this code is called when the lambda is defined. | ||
byte[] result = | ||
transformer.transform( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't immediately get why you wanted to change this, but I guess it is to reduce the helper classes and push more logic into the agent code. I think this is good idea and getting rid for the extra module for java9 is nice. What I'd change is that I'd probably also rename There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree on the I initially tried to simplify the design/API but that requires to introduce a new interface, so I thought maybe keep reusing I'll do another attempt by introducing a new interface to see if it helps improve this. |
||
targetClass.getClassLoader(), slashClassName, targetClass, null, classBytes); | ||
SylvainJuge marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (result != null) { | ||
classBytes = result; | ||
} | ||
} catch (Throwable throwable) { | ||
// sun.instrument.TransformerManager catches Throwable from ClassFileTransformer and ignores | ||
// it, we do the same. | ||
} | ||
|
||
return classBytes; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,11 +16,21 @@ public final class ClassFileTransformerHolder { | |
|
||
private static volatile ClassFileTransformer classFileTransformer; | ||
|
||
public static ClassFileTransformer getClassFileTransformer() { | ||
/** | ||
* get class transformer for defining lambdas | ||
* | ||
* @return class transformer for defining lambdas | ||
*/ | ||
public static ClassFileTransformer getLambdaClassFileTransformer() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [for reviewer] this is only used for lambda, and the |
||
return classFileTransformer; | ||
} | ||
|
||
public static void setClassFileTransformer(ClassFileTransformer transformer) { | ||
/** | ||
* set class transformer for defining lambdas | ||
* | ||
* @param transformer transformer | ||
*/ | ||
public static void setLambdaClassFileTransformer(ClassFileTransformer transformer) { | ||
classFileTransformer = transformer; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.tooling; | ||
|
||
import java.lang.instrument.ClassFileTransformer; | ||
import java.lang.instrument.IllegalClassFormatException; | ||
import java.security.ProtectionDomain; | ||
|
||
/** {@link ClassFileTransformer} for lambda instrumentation with java9 jpms module compatibility */ | ||
public class Java9LambdaClassFileTransformer implements ClassFileTransformer { | ||
|
||
private final ClassFileTransformer delegate; | ||
|
||
public Java9LambdaClassFileTransformer(ClassFileTransformer delegate) { | ||
this.delegate = delegate; | ||
} | ||
|
||
@Override | ||
public byte[] transform( | ||
ClassLoader loader, | ||
String className, | ||
Class<?> targetClass, | ||
ProtectionDomain protectionDomain, | ||
byte[] classfileBuffer) | ||
throws IllegalClassFormatException { | ||
|
||
if (targetClass == null) { | ||
// we expect the target class argument to be non-null, however it's only used to resolve | ||
// the JPMS module | ||
throw new IllegalStateException("can't resolve module without class"); | ||
} | ||
Module module = targetClass.getModule(); | ||
|
||
// lambda instrumentation happens only when the lambda is defined, thus the classBeingRedefined | ||
// must be null otherwise we get a partial instrumentation, for example virtual fields are not | ||
// properly applied | ||
return delegate.transform(module, loader, className, null, null, classfileBuffer); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,7 @@ | |
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; | ||
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess; | ||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; | ||
import java.lang.instrument.ClassFileTransformer; | ||
import java.lang.instrument.Instrumentation; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
|
@@ -63,7 +64,6 @@ | |
import net.bytebuddy.ByteBuddy; | ||
import net.bytebuddy.agent.builder.AgentBuilder; | ||
import net.bytebuddy.agent.builder.AgentBuilderUtil; | ||
import net.bytebuddy.agent.builder.ResettableClassFileTransformer; | ||
import net.bytebuddy.description.type.TypeDefinition; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.dynamic.DynamicType; | ||
|
@@ -199,9 +199,17 @@ private static void installBytebuddyAgent( | |
logger.log(FINE, "Installed {0} extension(s)", numberOfLoadedExtensions); | ||
|
||
agentBuilder = AgentBuilderUtil.optimize(agentBuilder); | ||
ResettableClassFileTransformer resettableClassFileTransformer = agentBuilder.installOn(inst); | ||
ClassFileTransformer transformer = agentBuilder.installOn(inst); | ||
if (JavaModule.isSupported()) { | ||
// wrapping in a JPMS compliant implementation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [for reviewer] wrapping at registration time helps to make the consumer transparently use it with java 8 API. |
||
transformer = new Java9LambdaClassFileTransformer(transformer); | ||
} else { | ||
// wrapping in a java 8 compliant transformer | ||
transformer = new LambdaClassFileTransformer(transformer); | ||
} | ||
ClassFileTransformerHolder.setLambdaClassFileTransformer(transformer); | ||
|
||
instrumentationInstalled = true; | ||
ClassFileTransformerHolder.setClassFileTransformer(resettableClassFileTransformer); | ||
|
||
addHttpServerResponseCustomizers(extensionClassLoader); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.tooling; | ||
|
||
import java.lang.instrument.ClassFileTransformer; | ||
import java.lang.instrument.IllegalClassFormatException; | ||
import java.security.ProtectionDomain; | ||
|
||
/** {@link ClassFileTransformer} for lambda instrumentation without jpms modules */ | ||
public class LambdaClassFileTransformer implements ClassFileTransformer { | ||
|
||
private final ClassFileTransformer delegate; | ||
|
||
public LambdaClassFileTransformer(ClassFileTransformer delegate) { | ||
this.delegate = delegate; | ||
} | ||
|
||
@Override | ||
public byte[] transform( | ||
ClassLoader loader, | ||
String className, | ||
Class<?> classBeingRedefined, | ||
ProtectionDomain protectionDomain, | ||
byte[] classfileBuffer) | ||
throws IllegalClassFormatException { | ||
|
||
// lambda instrumentation happens only when the lambda is defined, thus the classBeingRedefined | ||
// must be null otherwise we get a partial instrumentation, for example virtual fields are not | ||
// properly applied. | ||
return delegate.transform(loader, className, null, null, classfileBuffer); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,13 +11,13 @@ | |
import java.util.List; | ||
|
||
@AutoService(InstrumentationModule.class) | ||
public class InlineIbmResourceLevelInstrumentationModule extends InstrumentationModule { | ||
public InlineIbmResourceLevelInstrumentationModule() { | ||
super("inline-ibm-resource-level"); | ||
public class IbmResourceLevelInstrumentationModule extends InstrumentationModule { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [for reviewer] there is no need to maintain an inline and indy variants of this instrumentation, so we only need one that is compatible with both. |
||
public IbmResourceLevelInstrumentationModule() { | ||
super("ibm-resource-level"); | ||
} | ||
|
||
@Override | ||
public List<TypeInstrumentation> typeInstrumentations() { | ||
return singletonList(new InlineResourceLevelInstrumentation()); | ||
return singletonList(new ResourceLevelInstrumentation()); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.