opentelemetry-js
opentelemetry-js copied to clipboard
Make Singleton/Registration explicit
- [x] This only affects the JavaScript OpenTelemetry library
- [x] This may affect other libraries, but I would like to get opinions here first
Context
Hey there, I notice that some of the classes hide the fact that they register themselves as global objects, for example:
https://github.com/open-telemetry/opentelemetry-js/blob/c85fbe6682b9a8fd52e4b99bdbb079833b04e845/packages/opentelemetry-tracing/src/BasicTracerProvider.ts#L137
Such practices make sense once you know what is happening, but cause confusion to figure out why things are getting overwritten.
export const provider = new WebTracerProvider();
// Nothing says that `provider` will be registered globally since `register` itself take arguments.
// Am I registering context managers? Well, sort of, we are registering more than that.
provider.register({
contextManager: new ZoneContextManager()
});
Alternative could be,
export const provider = new WebTracerProvider({
contextManager: new ZoneContextManager()
});
// or even
provider.AddContextManger(new ZoneContextManager())
// Notice that I removed arguments, so the concept of `register` is a bit, but still confusing
provider.register();
Also this part, https://github.com/open-telemetry/opentelemetry-js/blob/f077df3f14414f8587282bdf54dff703d137d4b1/packages/opentelemetry-instrumentation/src/autoLoader.ts#L38-L41
Proposal
Remove implicitness global registration from Providers/Any global object.
import { trace } from '@opentelemetry/api';
import { registerProvider } from '@opentelemetry/api';
import { WebTracerProvider } from '@opentelemetry/web';
export const provider = new WebTracerProvider();
trace.registerProvider(provider);
Or implicit dependencies in the instrumentations.
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { WebTracerProvider } from '@opentelemetry/web';
export const provider = new WebTracerProvider();
const something = new MyInstrumentation({
tracerProvider: provider
// meterProvier: ...
})
something.setTracerProvider(provider);
registerInstrumentations({
instrumentation: [
something,
new MyInstrumentation({
tracerProvider: provider
// meterProvier: ...
}),
],
});
Notes
I would like to understand the decision made since it is not clear to me looking at the existing code; and from the first-hand experience, I had to debug code in order to understand the hidden (and important) registrations and the dependencies between them.
+1 to this. Its not very obvious whats happening with the current design.
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days.
We also need (should) address the implicit setting / usage of the global context, as this causes issues for multiple components that each want to have their own set of details.
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days.
keep
The sandbox is still in the process of getting setup -- it's realistically still a few months away before we will be starting to look to how we address this.