Description
Description
In the June 24th, 2021 SIG meeting we mentioned that the way Distro
and Configurator
are set up right now are not friendly for creating new distros because the implementation takes the 1st distro and the 1st configurator it finds installed instead of taking the one the user might want.
See:
Auto-instrumentation requires a distro to be installed. The opentelemetry-distro
package provides a Configurator
and an OpenTelemetryDistro
class. Auto-instrumentation then hooks into the Configurator AND the Distro to configure instrumentation.
Currently the Configurator
initializes components
def _initialize_components():
exporter_names = _get_exporter_names()
trace_exporters = _import_exporters(exporter_names)
id_generator_name = _get_id_generator()
id_generator = _import_id_generator(id_generator_name)
_init_tracing(trace_exporters, id_generator)
class Configurator(BaseConfigurator):
# pylint: disable=no-self-use
def _configure(self, **kwargs):
_initialize_components()
And the OpenTelemetryDistro
sets environment variables:
class OpenTelemetryDistro(BaseDistro):
"""
The OpenTelemetry provided Distro configures a default set of
configuration out of the box.
"""
# pylint: disable=no-self-use
def _configure(self, **kwargs):
os.environ.setdefault(OTEL_TRACES_EXPORTER, "otlp_proto_grpc_span")
Problem
If I want to create a new opentelemetry-distro-aws
distro, I really only want to set more environment variables like:
class AwsXrayOpenTelemetryDistro(OpenTelemetryDistro):
def _configure(self, **kwargs):
super._configure(kwargs)
os.environ.setdefault(OTEL_PROPAGATORS, "aws_xray")
but because the current implementation only takes the 1st distro, I have no guarantee my -aws
distro will be used for configuration.
Furthermore, if I like the Configurator
as is, I have to copy and paste the code in the current setup because again only 1 "distro" can be installed.
Potential Solutions
Some solutions we mentioned in the SIG meeting:
Option 1: Use an environment variable to select the distro you want out of all the ones installed
Use OTEL_PYTHON_SELECTED_DISTRO
to select the one you want.
PROs:
- It is similar to patterns we have elsewhere with environment variables?
CONS:
- Encourages installing multiple distros which is confusing
- Would require a user to BOTH
pip install opentelemetry-distro-aws
andexport OTEL_PYTHON_DISTRO=aws
which is confusing because a distro install should just work
Option 2: Move the useful "initalization" methods of the Configurator
and BaseDistro
into the opentelemetry-sdk
and use more virtual methods (i.e. with a default implementation) instead
This also means moving BaseDistro
out of opentelemetry-instrumentation
package and into opentelemetry-sdk
.
PROs:
- The
Configurator
_initialize_components()
code will probably be helpful to many distros so we should pull it out - More virtual methods will truly allow distros to only set environment variables and make small adjustments to the useful default implementations
- You only need to install 1 distro because we will have the right virtual methods to hook into so that downstream distros can use the useful default implementations and only make small changes. i.e.
- set environment variable
- customize
Instrumentor
"configuration options"
CONs:
- Specification doesn't really have guidance on this? But it's just using environment variables to initialize components as the spec requires so it should be fine.
- Making
_initialize_components()
the default means it assumes more of what we want, but it is probably what we want so as long as we expose the right methods to hook into we will still give distros the chance to customize
Summary
I think Option 2 is the clear preference. We just need to move BaseDistro
and the _initialize_components()
implementation to a common package (opentelemetry-sdk
for BaseDistro
? opentelemetry-instrumentation
for _initialize_components
?) and expose the right virtual/abstract methods in the BaseDistro
class.
We might even remove Configurator
all-together?