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

Unable to launch OTel Java Agent from an uber JAR #9702

Closed
rvesse opened this issue Oct 17, 2023 · 9 comments
Closed

Unable to launch OTel Java Agent from an uber JAR #9702

rvesse opened this issue Oct 17, 2023 · 9 comments
Labels
needs author feedback Waiting for additional feedback from the author stale

Comments

@rvesse
Copy link

rvesse commented Oct 17, 2023

Describe the bug

In a similar vein to #8227 I've been experimenting with whether you can package the Otel Agent JAR into an uber JAR and have that work. I'm pretty sure the answer is no this won't work, so it would be nice if this were explicitly stated that this isn't supported somewhere in the documentation

Firstly if you're attempting to package into an uber jar you need to set both the Premain-Class and Launcher-Agent-Class attributes in manifest.mf. It's Launcher-Agent-Class that actually starts the agent in an uber JAR deployment BUT if you don't have Premain-Class as well OTel baulks with the following error:

ERROR io.opentelemetry.javaagent.OpenTelemetryAgent
java.lang.IllegalStateException: The agent was not installed, because the agent was found in 'example.jar', which doesn't contain a Premain-Class manifest attribute. Make sure that you haven't included the agent jar file inside of an application uber jar.

Clearly implying that the authors didn't expect this to be supported anyway.

If you do specify the Premain-Class attribute to force your way past this error you'll get the following error on startup:

OpenTelemetry Javaagent failed to start
java.lang.IllegalStateException: Could not install class file transformer
at net.bytebuddy.agent.builder.AgentBuilder$Default.doInstall(AgentBuilder.java:11253)
at net.bytebuddy.agent.builder.AgentBuilder$Default.installOn(AgentBuilder.java:11155)
at net.bytebuddy.agent.builder.AgentBuilder$Default$Delegator.installOn(AgentBuilder.java:12927)
at io.opentelemetry.javaagent.tooling.AgentInstaller.installBytebuddyAgent(AgentInstaller.java:181)
at io.opentelemetry.javaagent.tooling.AgentInstaller.installBytebuddyAgent(AgentInstaller.java:94)
at io.opentelemetry.javaagent.tooling.AgentStarterImpl.start(AgentStarterImpl.java:78)
at io.opentelemetry.javaagent.bootstrap.AgentInitializer.initialize(AgentInitializer.java:35)
at io.opentelemetry.javaagent.OpenTelemetryAgent.startAgent(OpenTelemetryAgent.java:57)
at io.opentelemetry.javaagent.OpenTelemetryAgent.agentmain(OpenTelemetryAgent.java:49)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:491)
at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:513)
at java.instrument/sun.instrument.InstrumentationImpl.loadAgent0(Native Method)
at java.instrument/sun.instrument.InstrumentationImpl.loadAgent(InstrumentationImpl.java:556)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/sun.launcher.LauncherHelper.lambda$getMainClassFromJar$0(LauncherHelper.java:576)
at java.base/java.util.Optional.ifPresent(Optional.java:178)
at java.base/sun.launcher.LauncherHelper.getMainClassFromJar(LauncherHelper.java:571)
at java.base/sun.launcher.LauncherHelper.loadMainClass(LauncherHelper.java:778)
at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:686)
Caused by: java.lang.UnsupportedOperationException: adding retransformable transformers is not supported in this environment
at java.instrument/sun.instrument.InstrumentationImpl.addTransformer(InstrumentationImpl.java:96)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at net.bytebuddy.utility.Invoker$Dispatcher.invoke(Unknown Source)
at net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForNonStaticMethod.invoke(JavaDispatcher.java:1032)
at net.bytebuddy.utility.dispatcher.JavaDispatcher$ProxiedInvocationHandler.invoke(JavaDispatcher.java:1162)
at net.bytebuddy.agent.builder.$Proxy5.addTransformer(Unknown Source)
at net.bytebuddy.agent.builder.AgentBuilder$Default.doInstall(AgentBuilder.java:11230)
... 25 more

Which likely is the same underlying bug raphw/byte-buddy/issues/374 mentioned in the comments thread on #8227

Steps to reproduce

Generate an über JAR with the OTel Java Agent using the toolchain of your choice, e.g. Maven Shade plugin:

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <configuration>
          <shadedArtifactAttached>false</shadedArtifactAttached>
          <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
              <mainClass>my.package.MainClass</mainClass>
              <!-- https://issues.apache.org/jira/browse/LOG4J2-2537 -->
              <manifestEntries>
                <Multi-Release>true</Multi-Release>
                <Premain-Class>io.opentelemetry.javaagent.OpenTelemetryAgent</Premain-Class>
                <Launcher-Agent-Class>io.opentelemetry.javaagent.OpenTelemetryAgent</Launcher-Agent-Class>
              </manifestEntries>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
          </transformers>
          <filters>
            <filter>
              <artifact>*:*</artifact>
              <excludes>
                <!-- 
                     Some jars are signed but shading breaks that. 
                     Don't include signing files. 
                -->
                <exclude>META-INF/*.SF</exclude>
                <exclude>META-INF/*.DSA</exclude>
                <exclude>META-INF/*.RSA</exclude>
              </excludes>
            </filter>
          </filters>
        </configuration>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Expected behavior

N/A, seems this isn't intended to work/can't work so documentation merely needs to be clearer around this

Actual behavior

Errors thrown as shown earlier in description

Javaagent or library instrumentation version

1.24.0

Environment

JDK: Temurin 17 and OpenJDK 17
OS: Mac OX X Ventura, Linux (5.15.40-linuxkit)

Additional context

No response

@rvesse rvesse added bug Something isn't working needs triage New issue that requires triage labels Oct 17, 2023
@trask
Copy link
Member

trask commented Oct 17, 2023

hi @rvesse! is this feature what you're looking for? https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/runtime-attach

@trask trask added the needs author feedback Waiting for additional feedback from the author label Oct 17, 2023
@rvesse
Copy link
Author

rvesse commented Oct 17, 2023

hi @rvesse! is this feature what you're looking for? https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/runtime-attach

No, I don't think that solves the problem for Uber JARs anyway, I get a slightly different error condition but my application still crashes:

[otel.javaagent 2023-10-17 15:34:29:703 +0100] [Attach Listener] INFO io.opentelemetry.javaagent.tooling.VersionLogger - opentelemetry-javaagent - version: 0.20.1-SNAPSHOT
ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...

Personally I really don't want to put the agent into an uber JAR because that's not how agents are supposed to be used. But I'd ideally like some documentation saying Don't do that because X (or equivalent) in your official documentation so I point to that to justify why we aren't doing that.

@github-actions github-actions bot removed the needs author feedback Waiting for additional feedback from the author label Oct 17, 2023
@trask
Copy link
Member

trask commented Oct 17, 2023

No, I don't think that solves the problem for Uber JARs anyway

can you describe a bit more why not? runtime attach module should allows you to embed the agent in an uber jar (e.g. spring boot)

@laurit
Copy link
Contributor

laurit commented Oct 17, 2023

You probably get the UnsupportedOperationException because you didn't add Can-Retransform-Classes: true manifest attribute, you should also add Can-Redefine-Classes: true. Packaging the agent into an uberjar like that will take some effort to make it work, I think it would be easier to get it running by packaging the agent as a jar file into your uberjar. In the Launcher-Agent-Class unpack that jar and use an URLClassLoader and a bit of reflection to call premain in OpenTelemetryAgent. I haven't tried it myself so can't say for sure whether this is all that is needed. If you want to package the agent into the uberjar then you have to be aware that in

the agent adds the jar it is loaded from to boot class path, this may break your application.

@breedx-splk breedx-splk removed the bug Something isn't working label Oct 17, 2023
@rvesse
Copy link
Author

rvesse commented Oct 19, 2023

To summarise:

  • Packaging the agent into an uber JAR is theoretically possible (if appropriate manifest.mf attributes are set) but likely a very bad idea per @laurit's comment as your entire application ends up on the bootstrap classpath which can lead to all sorts of subtle and interesting class loading problems
  • Runtime Attach is an option (but at least for my use case/deployment environment doesn't work)

Note that I'm quite happy for you guys to close this as Won't Fix or your equivalent.

My main goal in filing this issue was to have some more easily discoverable discussion of this topic to help future engineers who get asked to try and do this and start Googling and don't waste too much time.

@alagusundarams
Copy link

@trask we are trying to use the agent with quarkus Uber jar and we end up getting the same exception as stated by @rvesse. Is this the limitation of otel agent with uber jars?

@trask
Copy link
Member

trask commented Mar 27, 2024

hi @alagusundarams! if Runtime Attach isn't working for you, can you open an issue in https://github.com/open-telemetry/opentelemetry-java-contrib?

@breedx-splk
Copy link
Contributor

Hi @alagusundarams and @rvesse -- did you open an issue in the contrib repo? If so, can you please mention it here? Thanks!

@breedx-splk breedx-splk added needs author feedback Waiting for additional feedback from the author and removed needs triage New issue that requires triage labels Jul 23, 2024
Copy link
Contributor

This has been automatically marked as stale because it has been marked as needing author feedback and has not had any activity for 7 days. It will be closed automatically if there is no response from the author within 7 additional days from this comment.

@github-actions github-actions bot added the stale label Jul 30, 2024
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs author feedback Waiting for additional feedback from the author stale
Projects
None yet
Development

No branches or pull requests

5 participants