Skip to content
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

indy instrumentation - leftovers migration #13074

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

SylvainJuge
Copy link
Contributor

@SylvainJuge SylvainJuge commented Jan 20, 2025

Should be the final step of #11457, hopefully completing it.

There are currently 5 overrides of isIndyModule() and the goal here is to remove all most of them, hence allowing to move forward with the next steps described in #13031

@SylvainJuge SylvainJuge mentioned this pull request Jan 21, 2025
36 tasks
@SylvainJuge SylvainJuge marked this pull request as ready for review January 21, 2025 15:10
@SylvainJuge SylvainJuge requested a review from a team as a code owner January 21, 2025 15:10
@@ -28,8 +32,17 @@ public boolean defaultEnabled(ConfigProperties config) {
}

@Override
public boolean isIndyModule() {
return false;
public void injectClasses(ClassInjector injector) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think having any invokedynamic-based instrumentation/proxies is a good idea for the lambda instrumentation: The reason is that we unecessarily risk recursions for the invokedynamic bootstrapping if lambdas are used in there in some unfortunate places, even if this is not the case right now.

I feel we should rather simply move those two classes to the agent bootstrap package, lambda instrumentation imo is special enough to justify this. Alternatively, we could directly inject the classes via injectedClassNames().

Copy link
Contributor Author

@SylvainJuge SylvainJuge Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, until moving those to the bootstrap package is further discussed I've switched to using injectedClassNames() in 45ead47

}

@Override
public byte[] transform(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] here we override the pre-java9 API and then resolve the class module from the class, this allows to transparently call it from code compiled with Java 8 API level.

In practice, there is only a single usage for this in the internal lambda instrumentation, which makes it equivalent to the (now removed) Java9LambdaTransformer.

instrumentationInstalled = true;
ClassFileTransformerHolder.setClassFileTransformer(resettableClassFileTransformer);
if (JavaModule.isSupported()) {
// wrapping in a JPMS compliant implementation
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

public class InlineIbmResourceLevelInstrumentationModule extends InstrumentationModule {
public InlineIbmResourceLevelInstrumentationModule() {
super("inline-ibm-resource-level");
public class IbmResourceLevelInstrumentationModule extends InstrumentationModule {
Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

@SylvainJuge SylvainJuge marked this pull request as draft January 22, 2025 15:08
*
* @return class transformer for defining lambdas
*/
public static ClassFileTransformer getLambdaClassFileTransformer() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[for reviewer] this is only used for lambda, and the ClassFileTransformer instances that are used here are very specific to lambda instrumentation, so renaming helps keep it clear.

@SylvainJuge SylvainJuge marked this pull request as ready for review January 23, 2025 10:17
Comment on lines 52 to 58
public List<String> injectedClassNames() {
return Arrays.asList(
"io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines.instrumentationannotations.AnnotationSingletons",
"io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines.instrumentationannotations.AnnotationInstrumentationHelper",
"io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines.instrumentationannotations.MethodRequest",
"io.opentelemetry.javaagent.instrumentation.kotlinxcoroutines.instrumentationannotations.MethodRequestCodeAttributesGetter");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of injecting all the helper did you consider adding a proxy for AnnotationInstrumentationHelper similarly to

public void injectClasses(ClassInjector injector) {
// we do not use ByteBuddy Advice dispatching in this instrumentation
// Instead, we manually call GraphqlSingletons via ASM
// Easiest solution to work with indy is to inject an indy-proxy to be invoked
injector
.proxyBuilder("io.opentelemetry.javaagent.instrumentation.graphql.v20_0.GraphqlSingletons")
.inject(InjectionMode.CLASS_ONLY);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure we have the choice here, as MethodRequest is being used directly used in WithSpanInstrumentation which uses ASM, also if MethodRequest is being injected then it's also pulling AnnotationSingletons which is using it to be injected as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could replace MethodRequest with Object in method signatures. We had similar issue in indy instrumentation where advice methods could not have helper classes in the signature, see #11873 What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that could work, I will try to see if we can easily do it.

If I understand what you aim to achieve here is only exposing the AnnotationInstrumentationHelper class to the instrumented code through an injected proxy, and then leave other classes called by the real AnnotationInstrumentationHelper class implementation as implementation details.

One of the downsides of this approach is that we loose the type-safety of the method signatures and need to introduce explicit casts to make it work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented it in 03aa810 and there aren't that many compromises on the code, so I think it was again a great suggestion @laurit !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants