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 load SPI in springboot #10921

Open
crossoverJie opened this issue Mar 21, 2024 · 8 comments
Open

Unable to load SPI in springboot #10921

crossoverJie opened this issue Mar 21, 2024 · 8 comments
Labels
bug Something isn't working

Comments

@crossoverJie
Copy link
Contributor

Describe the bug

When using java.net.spi.InetAddressResolverProvider, the custom SPI does not load properly.

Steps to reproduce

META-INF/services/java.net.spi.InetAddressResolverProvider: com.example.demo.MyAddressResolverProvider

java  -javaagent:opentelemetry-javaagent.jar \
      -jar target/demo-0.0.1-SNAPSHOT.jar

image

Expected behavior

Customized implementation takes effect successfully.

Actual behavior

Custom implementation does not take effect.

Javaagent or library instrumentation version

1.32.0

Environment

JDK:21
OS: Linux/MacOS

Additional context

When I use this command (without a javaagent):

java -jar  target/demo-0.0.1-SNAPSHOT.jar

It's work fine.

image

And the classloader is correct: URLClassPath$Loader@1211

When I use this command (with javaagent):

java  -javaagent:opentelemetry-javaagent.jar \
      -jar target/demo-0.0.1-SNAPSHOT.jar

image

The classloader is incorrect: URLClassPath$JarLoader@814. The JarLoader cannot load the springboot jar; it can only load the normal Maven project jar.

And this method cannot be called org.springframework.boot.loader.launch.JarLauncher#main.

If I don't use Spring Boot instead of a normal Maven project, it'll also work fine.

@crossoverJie crossoverJie added bug Something isn't working needs triage New issue that requires triage labels Mar 21, 2024
@laurit
Copy link
Contributor

laurit commented Mar 22, 2024

Do I understand correctly that the issue is that because agent tries to establish network connections it will trigger loading java.net.spi.InetAddressResolverProvider before spring boot has set up its class loader and because of that your custom implementation of java.net.spi.InetAddressResolverProvider won't be used? If that is the case have you considered packaging your java.net.spi.InetAddressResolverProvider implementation and the the corresponding META-INF/services file in the root of the jar along with spring boot launcher code. I think this way your provider should be found even if the agent triggers initializing the networking code.

@laurit laurit added the needs author feedback Waiting for additional feedback from the author label Mar 22, 2024
@steverao steverao removed the needs triage New issue that requires triage label Mar 23, 2024
@crossoverJie
Copy link
Contributor Author

If that is the case have you considered packaging your java.net.spi.InetAddressResolverProvider implementation and the the corresponding META-INF/services file in the root of the jar along with spring boot launcher code.

in the root of the jar

Thank you for your reply.

Could you please explain in detail how to achieve this?

@github-actions github-actions bot removed the needs author feedback Waiting for additional feedback from the author label Mar 23, 2024
@laurit
Copy link
Contributor

laurit commented Mar 25, 2024

Could you please explain in detail how to achieve this?

No, I can't, I'm not a spring boot user and don't know exactly how you'd do this. Spring boot questions are best asked from spring boot channels or stack overflow. In your place I'd start by manually modifying the jar and seeing whether it resolves the issue. If it helps I'd check the documentation for spring boot plugin for the build system in use, for example https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#packaging.layers.configuration looks promising.

@serkan-ozal
Copy link
Contributor

Hi @laurit @crossoverJie,

As @laurit mentioned, system-wide InetAddressResolver in the InetAddress is initialized by the OTEL Java agent through system classloader without your custom InetAddressResolver. Because your custom InetAddressResolver is not visible to system classloader, but Spring Boot's custom classloader.

When I have debug the code, I have seen that InetAddress initialization is triggered by HostResourceProvider (which calls HostResource.get() and then InetAddress.getLocalHost().getHostName()).

As a workaround, you can disable HostResourceProvider

  • by environment variable:
OTEL_JAVA_DISABLED_RESOURCE_PROVIDERS=otel.java.disabled.resource.providers.HostResourceProvider
  • or by system property:

-Dotel.java.disabled.resource-providers=otel.java.disabled.resource.providers.HostResourceProvider

@crossoverJie
Copy link
Contributor Author

@serkan-ozal Thank you for your reply.

-Dotel.java.disabled.resource-providers=otel.java.disabled.resource.providers.HostResourceProvider

I have added this system property, but it's not work for me.

I have created a demo repo; if you have time, you can give it a try.

@github-actions github-actions bot removed the needs author feedback Waiting for additional feedback from the author label Apr 2, 2024
@serkan-ozal
Copy link
Contributor

serkan-ozal commented Apr 2, 2024

@crossoverJie Sorry, it is my bad. I made an error while copy-pasting full classname of the HostResourceProvider :)

For the correct workaround, you can disable HostResourceProvider

  • by environment variable:
OTEL_JAVA_DISABLED_RESOURCE_PROVIDERS=io.opentelemetry.instrumentation.resources.HostResourceProvider
  • or by system property:
-Dotel.java.disabled.resource-providers=io.opentelemetry.instrumentation.resources.HostResourceProvider

I have tried with your example and verified that it works.

@crossoverJie
Copy link
Contributor Author

@serkan-ozal Thank you for your help. It works for me.

I found HostResourceProvider provides the attributes: host.name and host.arch, I will miss these attributes if I disable it.

Is there any other better solution?

@Cirilla-zmh
Copy link

Is there any other better solution?

Seems like the loading of InetAddressResolver leads this case. Can you load your MyAddressResolverProvider after initialization of agent, and replace the global resolver by reflection?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants