open-telemetry / open-telemetry/opentelemetry-python
feat(config): unify declarative and env-var configuration through a shared SDK orchestrator
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 19
Description
Motivation
Today there are two independent configuration paths that construct the SDK:
-
Env-var path —
_initialize_components()inopentelemetry/sdk/_configuration/__init__.pyorchestrates SDK init, but env-var reading is scattered across individual SDK classes (TracerProvider,BatchSpanProcessor,Resource,MeterProvider, sampling, etc.). Each class reads its ownOTEL_*vars at construction time. -
Declarative file path — modular
create_*/configure_*factory functions per signal (_tracer_provider.py,_logger_provider.py,_meter_provider.py,_propagator.py,_resource.py), but no top-level orchestrator that ties them together.
This split means:
- Env-var reading logic is duplicated or scattered, making it hard to maintain
- There's no single "apply this config" entry point for the declarative path
- The two paths can drift in behavior since they don't share construction logic
Proposal
1. Add a top-level configure_sdk(config) orchestrator
A single function that takes an OpenTelemetryConfiguration and calls all configure_* functions in the correct order:
def configure_sdk(config: OpenTelemetryConfiguration) -> None:
resource = create_resource(config.resource)
configure_tracer_provider(config.tracer_provider, resource)
configure_meter_provider(config.meter_provider, resource)
configure_logger_provider(config.logger_provider, resource)
configure_propagator(config.propagator)
2. Add an env-var-to-config adapter
A function that reads all OTEL_* env vars and produces an OpenTelemetryConfiguration, which then flows through the same configure_sdk() path:
def load_config_from_env() -> OpenTelemetryConfiguration:
"""Read OTEL_* env vars and build an OpenTelemetryConfiguration."""
...
End state
YAML file → load_config_file() → OpenTelemetryConfiguration → configure_sdk()
env vars → load_config_env() → OpenTelemetryConfiguration → configure_sdk()
Both paths converge on the same construction logic, eliminating drift.
Considerations
- Scattered env-var reads in constructors:
BatchSpanProcessor.__init__,TracerProvider.__init__, etc. read env vars when no explicit value is passed. Changing this touches public API surface and needs careful deprecation. - Spec requirement: Individual components must respect env vars when no explicit config value is provided. A pure "read everything upfront" approach needs to distinguish "not configured" from "explicitly set to default".
- Backwards compatibility: The existing
_OTelSDKConfigurator/_BaseConfiguratorpattern is used by distros. Any refactor needs to preserve that extension point. - Scope: This is a large refactor best done incrementally — start with
configure_sdk()for the declarative path, then gradually migrate env-var reading.
Related
- #3631 — declarative config tracking issue
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with _initialize_components() in opentelemetry/sdk/_configuration/init.py and the signal-specific _tracer_provider.py, _logger_provider.py, _meter_provider.py, _propagator.py, and _resource.py factories. Trace the existing _OTelSDKConfigurator and _BaseConfigurator extension points before defining the incremental scope. Done means the declarative path has a shared configure_sdk() entry point while preserving existing constructor behavior and distro compatibility.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100