Skip to content

Making it easier to create custom distros #551

Closed
open-telemetry/opentelemetry-python
#1937
@NathanielRN

Description

@NathanielRN

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:

logger.warning(
"Configuration of %s not loaded, %s already loaded",
entry_point.name,
configured,

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 and export 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?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions