spring-cloud-sleuth-otel
spring-cloud-sleuth-otel copied to clipboard
Manage dependency on grpc-netty-shaded
Is your feature request related to a problem? Please describe.
I'm using spring-cloud-sleuth-otel-autoconfigure-1.0.0-20210328.215254-111.jar:1.0.0-SNAPSHOT.
If io.opentelemetry:opentelemetry-exporter-otlp is used as documented, the app fails to run with the following exception
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'otelOtlpGrpcSpanExporter' defined in class path resource [org/springframework/cloud/sleuth/autoconfig/otel/OtelExporterConfiguration$OtlpExporterConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter]: Factory method 'otelOtlpGrpcSpanExporter' threw exception; nested exception is io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional channel service provider found. Try adding a dependency on the grpc-okhttp, grpc-netty, or grpc-netty-shaded artifact
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1598) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1562) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1451) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1338) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getIfAvailable(DefaultListableBeanFactory.java:2021) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.ObjectProvider.getIfAvailable(ObjectProvider.java:77) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.cloud.sleuth.autoconfig.otel.OtelAutoConfiguration.otelTracerProvider(OtelAutoConfiguration.java:93) ~[spring-cloud-sleuth-otel-autoconfigure-1.0.0-20210328.215254-111.jar:1.0.0-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.5.jar:5.3.5]
... 86 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter]: Factory method 'otelOtlpGrpcSpanExporter' threw exception; nested exception is io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional channel service provider found. Try adding a dependency on the grpc-okhttp, grpc-netty, or grpc-netty-shaded artifact
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.5.jar:5.3.5]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.5.jar:5.3.5]
... 108 common frames omitted
Caused by: io.grpc.ManagedChannelProvider$ProviderNotFoundException: No functional channel service provider found. Try adding a dependency on the grpc-okhttp, grpc-netty, or grpc-netty-shaded artifact
at io.grpc.ManagedChannelProvider.provider(ManagedChannelProvider.java:43) ~[grpc-api-1.35.0.jar:1.35.0]
at io.grpc.ManagedChannelBuilder.forTarget(ManagedChannelBuilder.java:76) ~[grpc-api-1.35.0.jar:1.35.0]
at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder.build(OtlpGrpcSpanExporterBuilder.java:129) ~[opentelemetry-exporter-otlp-trace-1.0.0.jar:na]
at org.springframework.cloud.sleuth.autoconfig.otel.OtelExporterConfiguration$OtlpExporterConfiguration.otelOtlpGrpcSpanExporter(OtelExporterConfiguration.java:104) ~[spring-cloud-sleuth-otel-autoconfigure-1.0.0-20210328.215254-111.jar:1.0.0-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.5.jar:5.3.5]
... 109 common frames omitted
Adding the dependency bellow solves this problem.
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.36.1</version>
</dependency>
Describe the solution you'd like
Manage grpc-netty-shaded in spring-cloud-sleuth-otel-dependencies.
I'm not sure if otel itself should manage this dependency instead of sleuth.
Describe alternatives you've considered Just mention it in the doc
The exception is coming from here (the component that uses grpc):
at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder.build(OtlpGrpcSpanExporterBuilder.java:129) ~[opentelemetry-exporter-otlp-trace-1.0.0.jar:na]
It's compileOnly in OTel, I'm not sure why. I think this should be transparent from the perspective of Sleuth, the exporter should come with a default client that is replaceable.
@jkwatson What do you think?
The exception is coming from here (the component that uses grpc):
at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder.build(OtlpGrpcSpanExporterBuilder.java:129) ~[opentelemetry-exporter-otlp-trace-1.0.0.jar:na]It's
compileOnlyin OTel, I'm not sure why. I think this should be transparent from the perspective of Sleuth, the exporter should come with a default client that is replaceable.@jkwatson What do you think?
It's compile-only in otel because we don't want to dictate the transport that the user might want to use for grpc. I suggest, if sleuth wants to be opinionated, to include the netty-shaded transport dependency. Be prepared for users running into dependency conflicts, though, since that is very common with grpc users from what I've seen.
So if I put Sleuth aside and just use OTel exporter alone, this means that the exporter is not usable out of the box, you need to go the extra mile, right?
As a user, this is not a very good user experience. This is expected in case of an API module but as a user of opentelemetry-exporter-otlp, I would expect it to work out of the box. I don't think that having a default dictates anything it just mean "it works but feel free to change things if you need".
Do the other exporters work out of the box or do they need extra dependencies?
As the error log says,
Try adding a dependency on the grpc-okhttp, grpc-netty, or grpc-netty-shaded artifact
the user has a choice of which dependencies to add. I think it's okay to add the dependency if documented.
But as a Spring Boot user, I don't want to specify the version of grpc-netty-***, I want sleuth or otel to manage the version of the dependencies.
So if I put Sleuth aside and just use OTel exporter alone, this means that the exporter is not usable out of the box, you need to go the extra mile, right? As a user, this is not a very good user experience. This is expected in case of an API module but as a user of
opentelemetry-exporter-otlp, I would expect it to work out of the box. I don't think that having a default dictates anything it just mean "it works but feel free to change things if you need".Do the other exporters work out of the box or do they need extra dependencies?
We've been leaving the decision of specific dependencies to particular opentelemetry distributions (for example, the auto-instrumentation agent, or various vendor-customized distributions thereof).
Any grpc-based exporter has this same issue...you need to provide a specific transport mechanism of your own in order for it to work.
If you think this decision is wrong, please open an issue/discussion in opentelemetry-java so it can be discussed more widely.
fyi: https://github.com/open-telemetry/opentelemetry-java/issues/3123
FYI, I chatted with @anuraaga about this last week and we both agree that this is something for distributions (like spring-cloud-sleuth-otel) to manage, rather than have the SDK include by default. I'll defer any other discussion to the opened issue.
@jkwatson I understand that you don't want to include the client. What I don't understand is why?
From the client perspective, this is not a good experience, users can use opentelemetry-exporter-otlp directly (without Sleuth) but they are not able to do this out of the box.
It seems that other exporter modules include a client. Do you happen to know why are they different? Is it because of the dependency conflicts you mentioned?
@jkwatson I understand that you don't want to include the client. What I don't understand is why? From the client perspective, this is not a good experience, users can use
opentelemetry-exporter-otlpdirectly (without Sleuth) but they are not able to do this out of the box.It seems that other exporter modules include a client. Do you happen to know why are they different? Is it because of the dependency conflicts you mentioned?
Let's please discuss this on the issue you opened, so the other maintainers have visibility into it.
There not being a default client and that being a bad user experience aside, why is it the responsibility of Sleuth to know what version of grpc etc work with the OTel library? Shouldn't OTel define in its BOM what versions work with it?
There not being a default client and that being a bad user experience aside, why is it the responsibility of Sleuth to know what version of grpc etc work with the OTel library? Shouldn't OTel define in its BOM what versions work with it?
There are many grpc transport implementations, and we want the user to choose what they want to use. Again, please comment on the issue that @jonatan-ivanov opened. This is not the place to debate this.
fyi: it seems okhttp is the default client lib for exporters now: https://github.com/open-telemetry/opentelemetry-java/pull/3785
These seem to indicate we can go ahead and shade in okhttp to use it as the default grpc exporter, removing the need for users to add grpc-netty / -shaded, instead needing absolutely no extra dependencies.
see: https://github.com/open-telemetry/opentelemetry-java/pull/3786
I think after this is released and Sleuth-OTel is updated, we can close this issue since the users don't need should not need to do anything by default and they can replace the client lib by managing their dependencies.
I think this should be fixed (see previous comment), also Sleuth reached the end of its OSS support timeline. We encourage to migrate to Micrometer Tracing.