Closed garry-cairns closed 1 month ago
Can you clarify whether you want to:
If your goal is the first option, the specification for MeterProvider, TracerProvider, and LoggerProvider each have language allowing updating configuration, though details are missing as to how exactly this works.
If your goal is the second option, each language ecosystem should ensure that it has utilities required for testing. In java, for example, we allow the global to be reset for test.
@jack-berg Apologies for the slow response. I wanted option two I think. For example, in Python the BatchSpanProcessor is not fork safe. In an environment where at process start time I don't know whether an application will fork I might want to set up the tracer/meter provider but register fork handlers to shut them down and reinitialize them in the child process(es) in the event of a fork. Right now in the Python implementation Once will prevent that without me doing a bunch of weird stuff. Is it fair to say this might be one to raise in Python rather than at the spec given your response as it relates to option two?
Is it fair to say this might be one to raise in Python rather than at the spec given your response as it relates to option two?
If your use case is around testing, then yes, I would raise it with the python community since its reasonable for SDKs to have tools to accommodate testing. If there are use cases outside of testing, I think we need to discuss more and possibly change the specification.
My use-case extends beyond testing yes. Basically I'm working on a large platform using a common entrypoint for a large number of services. There's no way to distinguish between a service that will fork and one that won't, and my ideal solution would be
os.register_at_fork(before=shutdown_telemetry, after_in_child=enable_telemetry)
where the two args there are callables, the latter of which is doing all the stuff we'd expect of instantiating a batch processor and registering an exporter with it and so on. Right now I'm prevented from doing so in Python and, based on what I can tell from the go implementation, elsewhere as well. I'm aware my situation may be rare but I think this would be a good pattern nonetheless.
Hmmm.. yes this does seem to be both rare but valid. 🙂
I've just encountered this issue but for meters in a testing use case and basically solved it in a pytest fixture by doing something like
import importlib
import pytest
import opentelemetry.metrics._internal
from opentelemetry.metrics import set_meter_provider
@pytest.fixture
def configure_meter_provider():
... # create the provider
set_meter_provider(provider)
yield
# teardown - reset the provider
importlib.reload(opentelemetry.metrics._internal)
def test_whatever(configure_meter_provider):
... # run some tests on emitted metrics
importlib.reload
causes these lines to be re-run which resets the global provider.
I would not recommend doing this in production but for tests it should be okay for now. But the fact that this is required suggests some room for improvement here.
@open-telemetry/technical-committee please take another look, is this something that needs to be addressed?
It is always possible to implement a wrapper provider that can still be set only once but internally allow to swap the delegate if the app requires it. So I don't think this requires a spec change. Having said that, many instrumentation implementations may retrieve Tracer/Meter etc at initialization time, so typically solving this at provider level is not enough.
We discussed in the TC:
We will not be adding a reset to global tracer provider as a general specification. There's a lot of issues that this would cause globally across all languages.
We recommend the following:
Closing the current issue as wontfix. Please open a new issue (or retitle + rephrase this one) if you have a more narrow suggestion.
There are circumstances in which I'd like to be able to "reset" the global tracer provider at runtime. For example, there are some features I disallow in my app unless an environment variable is set, and I'd like to be able to update the tracer provider to reflect that change if the variable gets set or unset during a run (a typical use-case here is unit testing).
This is currently prevented in the python implementation, and I believe in others also. In python this is achieved with
opentelemetry.util._once.Once.do_once
. While I understand why this is generally desirable, I think it would be useful to allow a force override, which could let people delete and re-initialize the global provider.