Fix Groovy OpenTelemetrySdk builder loading#8407
Conversation
| } | ||
|
|
||
| @Test | ||
| void builder_fromGroovyWithoutIncubator() throws Exception { |
There was a problem hiding this comment.
Nit: Could rename the test to buildFromGroovyWithoutIncubator
There was a problem hiding this comment.
Done in — the test is now named .
| if (cause instanceof RuntimeException) { | ||
| throw (RuntimeException) cause; | ||
| } | ||
| if (cause instanceof Error) { | ||
| throw (Error) cause; | ||
| } |
There was a problem hiding this comment.
Can you add some comments justifying the reasons for this handling?
There was a problem hiding this comment.
Added a comment in commit d5ffc54 explaining that reflection wraps the underlying incubator-path failure in InvocationTargetException, and that we rethrow RuntimeException and Error directly to preserve the original behavior.
| try { | ||
| return (OpenTelemetrySdk) | ||
| requireNonNull(CREATE_EXTENDED_OPEN_TELEMETRY_SDK_METHOD) | ||
| .invoke(null, openTelemetrySdk, configProvider); |
There was a problem hiding this comment.
Nit: Looking at the javadoc for invoke, it throws 3 checked exceptions:
- IllegalAccessException
- IllegalArgumentException
- InvocationTargetException
Might be good to add handling for IllegalArgumentException (although it is less likely since arguments are controlled).
There was a problem hiding this comment.
Good catch. I added explicit IllegalArgumentException handling in commit d5ffc54 as well.
| * io.opentelemetry.sdk.internal.SdkConfigProvider)}. | ||
| */ | ||
| OpenTelemetrySdkBuilder setConfigProvider(SdkConfigProvider configProvider) { | ||
| OpenTelemetrySdkBuilder setConfigProvider(Object configProvider) { |
There was a problem hiding this comment.
Question: Why was this changed to Object?
There was a problem hiding this comment.
I changed it to Object so the reflective path in OpenTelemetrySdkBuilder no longer depends on a narrower incubator-linked method signature while Groovy is eagerly inspecting the builder. The actual object passed is still the same internal config provider; this just keeps the optional incubator path behind reflection.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8407 +/- ##
=========================================
Coverage 90.88% 90.88%
- Complexity 7985 7989 +4
=========================================
Files 898 898
Lines 24107 24129 +22
Branches 2406 2408 +2
=========================================
+ Hits 21909 21930 +21
- Misses 1455 1458 +3
+ Partials 743 741 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Follow-up: I added focused coverage for the reflective error-handling branches in OpenTelemetrySdkBuilder (runtime exception, error, checked exception, illegal argument, and illegal access paths) and pushed that in commit aa2fdc1. This should address the remaining patch coverage gap from Codecov. |
|
Follow-up: the broad CI failures were coming from an Error Prone overload-order warning on the new helper in OpenTelemetrySdkBuilder, which was then treated as an error under the normal build settings. I aligned the overload parameter order and updated the new branch-coverage tests accordingly in commit e0d4b87. |
|
You need to run |
|
Hey I want to take a step back on this. This PR represents a precedent that we're going to jump through additional hoops to support groovy. We don't say anything about groovy or other JVM based languages in our versioning policy. And its not that a don't want to support these. But I don't understand what supporting entails. Groovy for example, has different class loading semantics that has runs into issues with the patterns we use to activate different capabilities based on whether or not certain dependencies are present. For example, the metrics, logs, and trace SDKs all behave differently based on whether I know the techniques we need to use to make these patterns work with the java class loader. I don't the ways in which groovy class loading is different. I do know that there are differences that are impactful though. Before establishing a precedent about groovy, I want more analysis to be done about those differences and what it means for the patterns we employ. I know that its a bigger scope than just solving an issue that appears to be self contained. But some seemingly simple issues have a big can of worms hiding under the surface and this is one of them. Groovy users can always get around these issues by including the compile only dependencies on their classpath. |
@jack-berg That’s a fair point. I’m happy to close this PR if you think the compile-only dependency workaround is sufficient for now, and that any broader JVM-language compatibility discussion should happen separately. |
|
Did you try using |
Fixes #8198
This avoids eager Groovy linkage of incubator-dependent SDK code by resolving IncubatingUtil.createExtendedOpenTelemetrySdk(...) reflectively in OpenTelemetrySdkBuilder instead of calling it directly.
Also adds a Groovy regression test covering OpenTelemetrySdk.builder().build() without incubator classes on the runtime classpath.