Skip to content

Transform inline advice to delegating advice and test indy modules#9508

Merged
laurit merged 15 commits into
open-telemetry:mainfrom
laurit:indy-advice
Sep 22, 2023
Merged

Transform inline advice to delegating advice and test indy modules#9508
laurit merged 15 commits into
open-telemetry:mainfrom
laurit:indy-advice

Conversation

@laurit

@laurit laurit commented Sep 20, 2023

Copy link
Copy Markdown
Contributor

This pr implements asm transformation logic to automatically transform our existing inline advice to delegating advice used with indy instrumentation modules. When reviewing keep in mind that this is intended as a temporary solution. I'd expect that finally we'll do the conversion manually. Automatic transformation lets us run tests with indy logic on our existing code and discover the instrumentations that need additional work. Currently the following transformations are performed:

  • set inline = false on Advice.OnMethodEnter and Advice.OnMethodExit
  • transform @Advice.Argument(readOnly = false) to @Advice.AssignReturned.ToArguments.ToArgument
  • transform @Advice.Return(readOnly = false) to @Advice.AssignReturned.ToReturned
  • transfrom @Advice.Local to entry advice return value and read it with @Advice.Enter in exit advice

There are instrumentations where these transformations do not work such as using both @Advice.Argument(readOnly = false) and @Advice.Local in same advice return value from on enter advice method, for these instrumentations indy was disabled. We'll need to see whether we can improve the transformation to handle these or rewrite the advice. Additional reasons why indy was disabled include

  • instrumentation needs to add a class in application loader
  • instrumentation uses a class in the same package as instrumented code to get access to package private members
  • instrumentations cooperate by using the same classes. Previously this worked because when both instrumentations were in the same class loader they both had the same helper class, now each has its own copy. In some cases we have made it so that instrumentations cooperate using a class in the boot loader we either need to apply this everywhere or perhaps instead of having each instrumentation module in separate instrumentation class loader have only one per application class loader.
  • application and agent contain the same classes. Results in a LinkageError because instrumentation class loader prefers the classes from the agent.
  • advice returns a helper class that is unavailable to the application code

// We need to update our documentation on that
// Added back the call to contextProvider.rewriteVirtualFieldsCalls(extendableAgentBuilder)
// to get more instrumentations running.
extendableAgentBuilder = contextProvider.rewriteVirtualFieldsCalls(extendableAgentBuilder);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adding back contextProvider.rewriteVirtualFieldsCalls got some more tests passing (I don't remember which one, would need to retest). I don't know why it was removed.

@JonasKunz JonasKunz Sep 20, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't know why it was removed
I removed it because Advices would now use VirtualField in static variables instead. Because the advices are not inlined, the virtual field calls are not rewritten anyway.

However, I forgot about the fact there also is the possibility of inserting virtual field calls via the low-level ASM api.
I would assume that the instrumentations which were failing without this added code do exactly that.

Maybe it would make sense to double check if this is true and then change the comment accordingly. (e.g. "rewriteVirtualFieldsCalls is required in case instrumentations make use of TypeTransformer.applyTransformer and insert lookups for virtual fields")?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. Part of what rewriteVirtualFieldsCalls was still necessary here, I split that out from it and called just that part.

@laurit laurit marked this pull request as ready for review September 20, 2023 10:46
@laurit laurit requested review from a team and JonasKunz September 20, 2023 10:46
String adviceMethodName,
MethodType adviceMethodType,
Object[] args) {
CallDepth callDepth = CallDepth.forClass(IndyBootstrap.class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Whoopise, good catch. In the elastic agent we also have a CallDepth class, but it encapsulates a ThreadLocal. Definitely a difference to keep in mind when we port over additional instrumentations.

@mateuszrzeszutek mateuszrzeszutek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice!

Comment on lines +319 to +320
* result.put("foo", foo);
* result.put("bar", bar);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of referring to locals by their names, could we just put them into the array directly and refer by indexes in OnExit? And just keep a <String, Integer> mapping here, in the code generation, if we need that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We could and it definitely would make sense if we intended to keep this code, but as this is a temporary hack I think it isn't really important. Currently instrumenting methods doesn't have shared state, this would require having it. I'll think about it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Right, kinda makes sense if it's a temporary thing. Feel free to ignore it then 👍

@trask trask left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

😎😍

@laurit laurit merged commit 7d22597 into open-telemetry:main Sep 22, 2023
@laurit laurit deleted the indy-advice branch September 22, 2023 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants