-
Notifications
You must be signed in to change notification settings - Fork 861
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
This is a POC implementation of OTEP 74, global instance management #724
Conversation
Codecov Report
@@ Coverage Diff @@
## master #724 +/- ##
============================================
- Coverage 78.58% 78.57% -0.02%
- Complexity 778 796 +18
============================================
Files 101 102 +1
Lines 2779 2824 +45
Branches 268 269 +1
============================================
+ Hits 2184 2219 +35
- Misses 493 500 +7
- Partials 102 105 +3
Continue to review full report at Codecov.
|
* @param tracerFactory A fully configured and ready to operate {@link TracerFactory} | ||
* implementation. | ||
*/ | ||
public static void setTracerFactory(TracerFactory tracerFactory) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to offer a set we need to have thin wrappers that allow changing the implementation.
TraceFactoryWrapper extends TraceFactory {
private volatile TraceFactory implementation;
// redirects all calls to the implementation.
}
This solves the problem when users hold a static reference to the factory, but does not solve it when the user holds a reference to a Tracer.
I think in Java we already solved the otep 74 by providing dynamic loading for the TraceFactory implementation and we don't need a set method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe that to be the case. If instrumentation gets a handle to a Tracer before the SDK has been initialized, then it will never be replaced with an implementation that has a functional Tracer implementation behind it. This sample POC provides for the API Tracer to have it's implementation swapped out when the SDK is initialized.
for (Entry<TracerKey, DefaultTracer> entry : existingTracers.entrySet()) { | ||
TracerKey key = entry.getKey(); | ||
entry.getValue().setImplementation(tracerFactory.get(key.getName(), key.getVersion())); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bogdandrutu here is where the tracer implementation is swapped out after the SDK has been initialized.
@@ -73,7 +84,10 @@ public static TracerFactory getTracerFactory() { | |||
* @since 0.1.0 | |||
*/ | |||
public static MeterFactory getMeterFactory() { | |||
return getInstance().meterFactory; | |||
if (instance.meterFactory.get() == null) { | |||
setMeterFactory(SpiOpenTelemetryProvider.makeSpiMeterFactory()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was expecting to see some logic that uses a global "deferred" factory here. I see two cases:
(1) The user is planning to call setXXXerFactory() later; they want a handle they can store now which becomes functional later
(2) The user has planned for dependency injection, in which case we can bypass the user of a deferred factory here and use the injected value.
What I see here looks different. If the value is used it forces a decision about SPI to happen--what if there's no value injected and the user is still planning to call setXXXFactory
? I don't see how that will work.
What I read in the code here is that if someone accesses the global
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR doesn't include having done anything with the Meter implementation, only Tracers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now. Inside the call to makeSpiXXXFactory
you get a default "deferred" impl if there's no SPI value.
@@ -73,7 +84,10 @@ public static TracerFactory getTracerFactory() { | |||
* @since 0.1.0 | |||
*/ | |||
public static MeterFactory getMeterFactory() { | |||
return getInstance().meterFactory; | |||
if (instance.meterFactory.get() == null) { | |||
setMeterFactory(SpiOpenTelemetryProvider.makeSpiMeterFactory()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now. Inside the call to makeSpiXXXFactory
you get a default "deferred" impl if there's no SPI value.
…er after an SDK has been installed.
Is this still needed? I think that offering the ServiceLoader option as the only option is good enough, here are the reasons why:
|
I'm unclear on the state of the relevant OTEP. Our current implementation on master doesn't implement the OTEP fully. This is only here as an example of what it would take to implement the OTEP fully for the TracerSdk. If we want to close it, I'm fine with that, since it wasn't intended to be a final implementation, in any case. :) |
For the moment trying to understand if just SPI is enough. As I tried to explain in the first reason someone can implement a "Swappable" tracer implementation using SPI, by having the Swappable implementation loaded with SPI and installing the real implementation by calling into the Swappable implementation. |
Currently the OTEP says that if language supports SPI we should use that and don't do all the other work. |
Yep. I understand it. As I said, I'm fine with closing this. I'm not sure if we're going to work with Spring Framework, and archaic J2EE containers yet, but we can cross that bridge when @kbrockhoff gets to it. ;) |
What I want is a hidden thing :)). I want to make you work a bit to prove me wrong/right that someone can or cannot build an implementation of the API (using SPI) that supports delayed initialization for the Tracer class. |
Heh. I'm 100% sure it can be done. I mostly wanted to do this as an exercise to see what it might look like. |
See open-telemetry/oteps#74
This PR only handles the replacement of Tracer instances, but it gives a good indication of what it would look like for Meters as well.