spring-cloud-sleuth-otel icon indicating copy to clipboard operation
spring-cloud-sleuth-otel copied to clipboard

Manage dependency on grpc-netty-shaded

Open making opened this issue 4 years ago • 12 comments

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

making avatar Mar 30 '21 14:03 making

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?

jonatan-ivanov avatar Mar 30 '21 23:03 jonatan-ivanov

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?

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.

jkwatson avatar Mar 30 '21 23:03 jkwatson

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?

jonatan-ivanov avatar Mar 31 '21 00:03 jonatan-ivanov

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.

making avatar Mar 31 '21 01:03 making

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.

jkwatson avatar Mar 31 '21 02:03 jkwatson

fyi: https://github.com/open-telemetry/opentelemetry-java/issues/3123

jonatan-ivanov avatar Apr 06 '21 22:04 jonatan-ivanov

fyi: open-telemetry/opentelemetry-java#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 avatar Apr 06 '21 22:04 jkwatson

@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?

jonatan-ivanov avatar Apr 06 '21 23:04 jonatan-ivanov

@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?

Let's please discuss this on the issue you opened, so the other maintainers have visibility into it.

jkwatson avatar Apr 06 '21 23:04 jkwatson

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?

shakuzen avatar Apr 07 '21 02:04 shakuzen

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.

jkwatson avatar Apr 07 '21 03:04 jkwatson

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.

jonatan-ivanov avatar Oct 26 '21 17:10 jonatan-ivanov

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.

jonatan-ivanov avatar Jul 12 '24 18:07 jonatan-ivanov