diff --git a/CHANGELOG.md b/CHANGELOG.md index 9def2f55eb..052a18e608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.3.0-0.22b0...HEAD) +- `opentelemetry-instrumentation` Enforce 1 distro+configurator for auto instrumentation + ([#571](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/571)) - `opentelemetry-sdk-extension-aws` Update AWS entry points to match spec ([#566](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/566)) - Include Flask 2.0 as compatible with existing flask instrumentation diff --git a/opentelemetry-instrumentation/README.rst b/opentelemetry-instrumentation/README.rst index 6f74d2232f..c445f6ed60 100644 --- a/opentelemetry-instrumentation/README.rst +++ b/opentelemetry-instrumentation/README.rst @@ -38,6 +38,13 @@ opentelemetry-instrument opentelemetry-instrument python program.py +**NOTE:** `opentelemetry-instrument` will check for compatible "distros" (like `opentelemetry-distro`) +when automatically instrumenting. A "distro" is defined as a class that successfully inherits from the +[BaseDistro](https://github.com/open-telemetry/opentelemetry-python-contrib/blob/main/opentelemetry-instrumentation/src/opentelemetry/instrumentation/distro.py#L30). +If multiple distros are found, auto-instrumentation will fail. Check out +`Github Issue #551 `_ for +more details. + The instrument command will try to automatically detect packages used by your python program and when possible, apply automatic tracing instrumentation on them. This means your program will get automatic distributed tracing for free without having to make any code changes diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py index d89b60ec56..c1799a1085 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py @@ -31,26 +31,34 @@ logger = getLogger(__file__) -def _load_distros() -> BaseDistro: - for entry_point in iter_entry_points("opentelemetry_distro"): - try: - distro = entry_point.load()() - if not isinstance(distro, BaseDistro): - logger.debug( - "%s is not an OpenTelemetry Distro. Skipping", - entry_point.name, - ) - continue - logger.debug( - "Distribution %s will be configured", entry_point.name +def _load_distro() -> BaseDistro: + entry_points = iter_entry_points("opentelemetry_distro") + try: + first_distro = next(entry_points) + except StopIteration: + logger.warning( + "Failed to find even one installed distro. Initializing Auto Instrumentation without using a distro." + ) + return DefaultDistro() + + try: + more_distros = [ep.module_name for ep in entry_points] + + if more_distros: + logger.error( + "Multiple distros were found: (%s). Only one should be installed.", + ",".join([first_distro.module_name] + more_distros), ) - return distro - except Exception as exc: # pylint: disable=broad-except - logger.exception( - "Distribution %s configuration failed", entry_point.name + raise RuntimeError( + "Cannot Auto Instrument with multiple distros installed." ) - raise exc - return DefaultDistro() + + return first_distro.load()() + except Exception as exc: # pylint: disable=broad-except + logger.exception( + "Distribution %s configuration failed", first_distro.module_name + ) + raise exc def _load_instrumentors(distro): @@ -105,7 +113,7 @@ def _load_configurators(): def initialize(): try: - distro = _load_distros() + distro = _load_distro() distro.configure() _load_configurators() _load_instrumentors(distro)