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

First POC for external extension loading #2774

Closed
wants to merge 7 commits into from

Conversation

iNikem
Copy link
Contributor

@iNikem iNikem commented Apr 12, 2021

Please start reading from ExtensionClassLoader.

This is the first attempt to address #2442. Manual testing confirmed that this works.

Copy link
Member

@trask trask left a comment

Choose a reason for hiding this comment

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

any thoughts on class loader isolation, so extensions can bring their own version of grpc/netty and not cause conflicts? or should we table that aspect for now

* This classloader is used to load arbitrary extensions for Otel Java instrumentation agent. Such
* extensions may include SDK components (exporters or propagators) and additional instrumentations.
* They have to be isolated and shaded to reduce interference with the user application and to make
* it compatible with shaded SDK used by the agent.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* it compatible with shaded SDK used by the agent.
* it compatible with shaded API used by the agent.

Comment on lines +42 to +44
rule(
"#io.opentelemetry.extension.aws",
"#io.opentelemetry.javaagent.shaded.io.opentelemetry.extension.aws"),
Copy link
Member

Choose a reason for hiding this comment

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

I forget why this needs to be shaded..

Copy link
Contributor

Choose a reason for hiding this comment

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

This is the x-ray propagator - I think it's to be able to inject into user classloader for use from instrumentation, even if they have their own (potentially incompatible) one. Since extension instrumentation may use the propagator it seems appropriate to shade here too.

// TODO add support for system properties
URL extension = parseLocation(System.getenv("OTEL_JAVAAGENT_EXTENSIONS"));
if (extension != null) {
return new ExtensionClassLoader(extension, parent);
Copy link
Member

Choose a reason for hiding this comment

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

should we only handle OTEL_JAVAAGENT_EXTENSIONS pointing to a directory, and use all *.jar in that directory? we will want that option I think for easy dropping in of multiple extensions, and may be reasonable to only support that option (simpler doc story not to have multiple meanings of OTEL_JAVAAGENT_EXTENSIONS)

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 would support both single file and a directory.


public ExtensionClassLoader(URL url, ClassLoader parent) {
super(new URL[] {url}, parent);
this.manifest = getManifest(url);
Copy link
Member

Choose a reason for hiding this comment

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

oh, I remember this, I'm not sure how to generalize this to more than one jar file under the constraint of using URLClassLoader

maybe we can pass URLs to URLClassLoader that have custom InputStreams that do the shading? If that can work somehow (big if) then URLClassLoader will take care of the class/package definitions for us and we don't need the manifest

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm... in fact we can do this, I think... I will give it a try.

@iNikem
Copy link
Contributor Author

iNikem commented Apr 13, 2021

What isolation of what from what are you thinking about? :) One extension jar from another? Extensions from AgentClassLoader?

@trask
Copy link
Member

trask commented Apr 13, 2021

What isolation of what from what are you thinking about? :) One extension jar from another? Extensions from AgentClassLoader?

these are good questions 😁, ideally all of the above(?), but don't want to over-engineer it either

@iNikem
Copy link
Contributor Author

iNikem commented Apr 13, 2021

Extensions are already loaded from a separate classloader, which is a child of AgentClassLoader. Meaning nobody should see their classes. Extensions themselves should have access to agent classes, thus AgentClassLoader as a parent. This current state + possible separating extensions from each other - is it Ok or do we want more?

@iNikem iNikem force-pushed the extensions branch 2 times, most recently from 9104930 to 27f17cd Compare April 13, 2021 17:44
@iNikem iNikem requested a review from laurit as a code owner April 23, 2021 13:36
inputs.files(layout.files(shadowTask))

doFirst {
jvmArgs("-Dio.opentelemetry.smoketest.agent.shadowJar.path=/Users/nsalnikovtarnovski/Documents/workspace/opentelemetry-java-instrumentation/javaagent/build/libs/opentelemetry-javaagent-1.2.0-SNAPSHOT-all.jar")
Copy link
Member

Choose a reason for hiding this comment

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

You probably need to pass some other javaagent path here 😄

@@ -34,21 +34,27 @@ private static synchronized void startAgent(Instrumentation inst, URL bootstrapU
throws Exception {
if (AGENT_CLASSLOADER == null) {
ClassLoader agentClassLoader = createAgentClassLoader("inst", bootstrapUrl);
AGENT_CLASSLOADER = agentClassLoader;

Class<?> agentInstallerClass =
agentClassLoader.loadClass("io.opentelemetry.javaagent.tooling.AgentInstaller");
Copy link
Member

Choose a reason for hiding this comment

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

If agentClassLoader is an ExtensionClassLoader then won't we put AgentInstaller in the same CL as extensions? And won't it apply shading transformations on all agent classes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, because ExtensionClassLoader first delegates to parent, as usual. And its parent is the old AgentClassLoader


@Override
public InputStream getResourceAsStream(String name) {
InputStream originalStream = super.getResourceAsStream(name);
Copy link
Member

Choose a reason for hiding this comment

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

Missing if (originalStream == null)

@iNikem iNikem marked this pull request as draft May 6, 2021 11:04
@iNikem iNikem closed this May 18, 2021
@iNikem iNikem deleted the extensions branch July 18, 2021 19:29
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