Skip to content

Decide whether to use isolate or inject helper classes based on the advice classes#17815

Merged
trask merged 8 commits into
open-telemetry:mainfrom
laurit:inspect-advice
Apr 24, 2026
Merged

Decide whether to use isolate or inject helper classes based on the advice classes#17815
trask merged 8 commits into
open-telemetry:mainfrom
laurit:inspect-advice

Conversation

@laurit

@laurit laurit commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

When switching to indy instrumentation we need some way to tell whether an instrumenation is ready for indy or not. Currently we default to always using inline instrumenation and with -PtestIndy=true we switch all instrumentations to indy. We need some sort of middle ground where everything that we bundle runs with indy but user extensions could still run with inline if they are not ready for indy.
This PR introduce experimental api for instumentation modules to choose whether they want to inject helper classes to the application class loader or load them into separate class loader. Implementing this api is optional, in muzzle plugin we'll inspect the advice used by the instrumentation and guess based on the advice what the instrumentation module should use. Finally we'll fall back to applying the same heuristics used by muzzle during runtime.

@laurit
laurit requested a review from a team as a code owner April 10, 2026 14:18
@laurit
laurit requested a review from SylvainJuge April 10, 2026 14:18
@laurit
laurit marked this pull request as draft April 10, 2026 18:35
@laurit laurit changed the title Inspect advice to determine whether to use indy instrumentation Decide whether to use isolate or inject helper classes based on the advice classes Apr 22, 2026
@laurit
laurit marked this pull request as ready for review April 22, 2026 13:41

@SylvainJuge SylvainJuge left a comment

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.

With this approach, we load all of the helper classes of an instrumentation module in the target CL or in the isolated classloader.

As we want to get rid of the getModuleGroup, which also relates to where helper classes are loaded, I wonder if we should instead provide a per-class indication of where the helper class should be loaded instead.

}

@Nullable
public Boolean useIsolatedAdvice(

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 would suggest to rename this method to reflect the fact that this is an heuristic where we infer from the advice classes that inline=false is indy and inline=true is inline.

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.

At least in the public api and docs we'll need to replace indy with something else, I think we could use isolated.

his is an heuristic where we infer from the advice classes that inline=false is indy and inline=true is inline.

Added a bit of javadoc to the class. Is that enough?

* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
enum HelperClassStrategy {

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.

do you think we could reduce to having only 2 values here ?

  • injected (default) for the current behavior with inline=true, where the helper classes are just injected into the target CL
  • isolated (opt-in) for when we want to isolate helper classes.

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.

instead of DEFAULT we could return null, is this what you meant?

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.

No, I was thinking there are only 2 possible states for the "outcome" of this method return value:

  • using isolated classloader for helper classes
  • using injected helper classes

I did not realize that the third option does in fact help with the migration, in particular for extensions, as it allows to opt-in though configuration and then find any potential issues before having to make changes to the extensions.

Maybe it's a detail, but do you think we should explicitly implement this experimental method for all the internal instrumentation or should we rely on muzzle ?

  • ISOLATED for the vast majority of helper classes (at least for the modules that do not require a shared classloader)
  • INJECTED for the modules that do require a shared classloader

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.

I wasn't planning to implement it, but rely on auto-detection. We could try to make some kind of test that verifies that this is working as expected. I think we have one or two module (internal class loader) where auto-detection could choose injected. The class loader module is an outlier as it only works with isolated by really behaving as injected. Could consider leaving it as injected or alternatively making it work with isolated (might not be easy).

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 think that leaving class loader module as injected would definitely be fine, as it's definitely an outlier.

@laurit

laurit commented Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

With this approach, we load all of the helper classes of an instrumentation module in the target CL or in the isolated classloader.
As we want to get rid of the getModuleGroup, which also relates to where helper classes are loaded, I wonder if we should instead provide a per-class indication of where the helper class should be loaded instead.

The main concern in this PR is to allow using the new indy mode while also retaining the compatibility with existing extensions that use inline advice.
Getting rid of getModuleGroup is a separate topic. In experimental api we have injectedClassNames that allows injecting selected classes into instrumented class loader instead of placing them in the isolated class loader. I think we need to introduce a similar method or perhaps something similar to isHelperClass that would let us marks some classes as shared so they would be loaded by the agent class loader. Another option would be to change the class loading order for instrumentation class loader so that it would first load from agent. Then we probably could achieve sharing classes by instructing it to load shared classes from agent instead of defining them in the instrumentation class loader. Yet another option would be to express in isHelperClass that certain classes are not really helper classes then these classes would be loaded from the agent class loader. The problem with this is that we can't do it right now without breaking running these instrumentations as inline instrumentations, we't at least need a temporary measure before we can commit to not supporting inline any more. I think that another problem would be that in isHelperClass only true is really relevant so shared classes would need to be in a package that is not matched by one of the default helper class predicates.

@trask
trask requested a review from Copilot April 23, 2026 14:42

Copilot AI left a comment

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

@trask
trask merged commit 1b3d530 into open-telemetry:main Apr 24, 2026
93 checks passed
@laurit
laurit deleted the inspect-advice branch April 24, 2026 19:44
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.

4 participants