From e20d0493fa46bdd290d3cd11a07547306ed3a83a Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Tue, 16 Jun 2026 13:09:26 +0100 Subject: [PATCH 1/3] docs: add declarative configuration guide and example Add an SDK documentation page covering declarative (file-based) configuration via OTEL_CONFIG_FILE and the public configuration API, plus a runnable example under docs/examples/declarative-config with a schema-1.0 YAML config. --- docs/examples/declarative-config/README.rst | 96 ++++++++++++ docs/examples/declarative-config/app.py | 22 +++ .../declarative-config/otel-config.yaml | 34 +++++ docs/sdk/configuration.rst | 139 ++++++++++++++++++ docs/sdk/index.rst | 1 + 5 files changed, 292 insertions(+) create mode 100644 docs/examples/declarative-config/README.rst create mode 100644 docs/examples/declarative-config/app.py create mode 100644 docs/examples/declarative-config/otel-config.yaml create mode 100644 docs/sdk/configuration.rst diff --git a/docs/examples/declarative-config/README.rst b/docs/examples/declarative-config/README.rst new file mode 100644 index 00000000000..7d438f007b9 --- /dev/null +++ b/docs/examples/declarative-config/README.rst @@ -0,0 +1,96 @@ +Declarative Configuration +========================= + +This example configures the OpenTelemetry SDK from a single YAML file using +:doc:`declarative configuration ` instead of environment +variables or hand-written provider setup. + +The source files of this example are available :scm_web:`here +`. + +Install the SDK with the ``file-configuration`` extra (it pulls in ``pyyaml`` +and ``jsonschema``) along with the OTLP/HTTP exporter: + +.. code-block:: sh + + pip install "opentelemetry-sdk[file-configuration]" \ + opentelemetry-exporter-otlp-proto-http + +Start an OTLP-capable backend locally so there is somewhere to send data. Write +the following file: + +.. code-block:: yaml + + # otel-collector-config.yaml + receivers: + otlp: + protocols: + http: + endpoint: 0.0.0.0:4318 + + exporters: + debug: + verbosity: detailed + + service: + pipelines: + traces: + receivers: [otlp] + exporters: [debug] + metrics: + receivers: [otlp] + exporters: [debug] + logs: + receivers: [otlp] + exporters: [debug] + +Then start the Collector: + +.. code-block:: sh + + docker run \ + -p 4318:4318 \ + -v $(pwd)/otel-collector-config.yaml:/etc/otel-collector-config.yaml \ + otel/opentelemetry-collector:latest \ + --config=/etc/otel-collector-config.yaml + +Apply the configuration programmatically +---------------------------------------- + +``app.py`` loads ``otel-config.yaml`` and applies it with ``configure_sdk``: + +.. code-block:: python + + from opentelemetry.sdk.configuration import configure_sdk, load_config_file + + configure_sdk(load_config_file("otel-config.yaml")) + +Run it: + +.. code-block:: sh + + python app.py + +You should see the exported span in the Collector's debug output. + +Apply the configuration with an environment variable +---------------------------------------------------- + +Alternatively, point the SDK at the file with ``OTEL_CONFIG_FILE`` and let +auto-instrumentation apply it — no configuration code in your application: + +.. code-block:: sh + + export OTEL_CONFIG_FILE=$(pwd)/otel-config.yaml + opentelemetry-instrument python app.py + +Environment variable substitution +---------------------------------- + +``otel-config.yaml`` uses ``${DEPLOYMENT_ENVIRONMENT:-development}`` to read the +deployment environment from the environment, defaulting to ``development``. Set +it before running to override: + +.. code-block:: sh + + export DEPLOYMENT_ENVIRONMENT=staging diff --git a/docs/examples/declarative-config/app.py b/docs/examples/declarative-config/app.py new file mode 100644 index 00000000000..27fba9c60e7 --- /dev/null +++ b/docs/examples/declarative-config/app.py @@ -0,0 +1,22 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +"""Configure the OpenTelemetry SDK from a declarative configuration file. + +Run an OTLP-capable backend (for example the OpenTelemetry Collector) on +localhost:4318, then run this script to emit a span using the configuration +in ``otel-config.yaml``. +""" + +from pathlib import Path + +from opentelemetry import trace +from opentelemetry.sdk.configuration import configure_sdk, load_config_file + +config_path = Path(__file__).parent / "otel-config.yaml" +configure_sdk(load_config_file(config_path)) + +tracer = trace.get_tracer("declarative-config-example") + +with tracer.start_as_current_span("hello"): + print("Hello from a declaratively configured SDK!") diff --git a/docs/examples/declarative-config/otel-config.yaml b/docs/examples/declarative-config/otel-config.yaml new file mode 100644 index 00000000000..1f2bd9fa798 --- /dev/null +++ b/docs/examples/declarative-config/otel-config.yaml @@ -0,0 +1,34 @@ +file_format: "1.0" + +resource: + attributes: + - name: service.name + value: my-service + - name: deployment.environment.name + value: ${DEPLOYMENT_ENVIRONMENT:-development} + +tracer_provider: + processors: + - batch: + exporter: + otlp_http: + endpoint: http://localhost:4318/v1/traces + sampler: + parent_based: + root: + always_on: {} + +meter_provider: + readers: + - periodic: + interval: 60000 + exporter: + otlp_http: + endpoint: http://localhost:4318/v1/metrics + +logger_provider: + processors: + - batch: + exporter: + otlp_http: + endpoint: http://localhost:4318/v1/logs diff --git a/docs/sdk/configuration.rst b/docs/sdk/configuration.rst new file mode 100644 index 00000000000..e1354f140ec --- /dev/null +++ b/docs/sdk/configuration.rst @@ -0,0 +1,139 @@ +Declarative Configuration +========================= + +Declarative configuration lets you configure the OpenTelemetry SDK from a +single YAML (or JSON) file instead of setting many individual ``OTEL_*`` +environment variables or writing provider-construction code by hand. The file +format is defined by the `OpenTelemetry configuration specification +`_. + +A single file describes your resource, providers, processors, exporters, +samplers, and propagators. The SDK reads the file, validates it against the +configuration schema, and applies it globally. + +Installing +---------- + +File configuration relies on optional dependencies (``pyyaml`` and +``jsonschema``). Install them with the ``file-configuration`` extra: + +.. code-block:: sh + + pip install "opentelemetry-sdk[file-configuration]" + +Enabling with an environment variable +------------------------------------- + +The simplest way to use declarative configuration is to point the SDK at a +file with the ``OTEL_CONFIG_FILE`` environment variable. When it is set, the +file is the sole source of configuration and other ``OTEL_*`` variables are +ignored (except where referenced inside the file — see +`Environment variable substitution`_). + +.. code-block:: sh + + export OTEL_CONFIG_FILE=/etc/otel/otel-config.yaml + opentelemetry-instrument python app.py + +Configuring programmatically +---------------------------- + +You can also load and apply a configuration file directly. This is useful when +you want to construct or inspect the configuration in code: + +.. code-block:: python + + from opentelemetry.sdk.configuration import configure_sdk, load_config_file + + config = load_config_file("otel-config.yaml") + configure_sdk(config) + +``load_config_file`` parses and validates the file and returns a typed +``OpenTelemetryConfiguration`` object; ``configure_sdk`` applies it to the +global tracer, meter, and logger providers and the global propagator. A failure +to read, parse, or validate the file raises ``ConfigurationError``. + +Example configuration +--------------------- + +The following file configures traces, metrics, and logs to be exported over +OTLP/HTTP. The source is available :scm_web:`here +`. + +.. code-block:: yaml + + file_format: "1.0" + + resource: + attributes: + - name: service.name + value: my-service + - name: deployment.environment.name + value: ${DEPLOYMENT_ENVIRONMENT:-development} + + tracer_provider: + processors: + - batch: + exporter: + otlp_http: + endpoint: https://api.honeycomb.io/v1/traces + headers: + - name: x-honeycomb-team + value: ${HONEYCOMB_API_KEY} + sampler: + parent_based: + root: + always_on: {} + + meter_provider: + readers: + - periodic: + interval: 60000 + exporter: + otlp_http: + endpoint: https://api.honeycomb.io/v1/metrics + headers: + - name: x-honeycomb-team + value: ${HONEYCOMB_API_KEY} + + logger_provider: + processors: + - batch: + exporter: + otlp_http: + endpoint: https://api.honeycomb.io/v1/logs + headers: + - name: x-honeycomb-team + value: ${HONEYCOMB_API_KEY} + +Environment variable substitution +---------------------------------- + +Values in the file may reference environment variables, which keeps secrets +such as API keys out of the file itself. Substitution happens before the file +is parsed. + +* ``${VAR}`` — replaced with the value of ``VAR``. If ``VAR`` is unset, loading + fails with an error. +* ``${VAR:-default}`` — replaced with ``VAR`` if set, otherwise ``default``. +* ``$$`` — a literal ``$``. + +In the example above, ``${HONEYCOMB_API_KEY}`` is required, while +``${DEPLOYMENT_ENVIRONMENT:-development}`` falls back to ``development`` when +unset. + +Behavior notes +-------------- + +* When ``OTEL_CONFIG_FILE`` is set, the file is authoritative; other ``OTEL_*`` + environment variables are not consulted. +* Sections omitted from the file leave the corresponding global provider + unset (a no-op provider), per the specification. +* Setting ``disabled: true`` at the top level turns the SDK into a no-op. + +See also +-------- + +* `OpenTelemetry configuration specification + `_ +* :doc:`environment_variables` — the environment-variable configuration path diff --git a/docs/sdk/index.rst b/docs/sdk/index.rst index ecc4a390856..48c3568eab6 100644 --- a/docs/sdk/index.rst +++ b/docs/sdk/index.rst @@ -20,3 +20,4 @@ processed, and exported. metrics error_handler environment_variables + configuration From 04fc8392cbea27f6b66bc46f9cabc88effac7384 Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Tue, 16 Jun 2026 13:26:43 +0100 Subject: [PATCH 2/3] docs: use vendor-neutral OTLP endpoint in config example Replace the Honeycomb-specific endpoint and headers in the declarative config guide with a generic OTLP endpoint and api-key header. --- docs/sdk/configuration.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/sdk/configuration.rst b/docs/sdk/configuration.rst index e1354f140ec..dad5a5c1c0f 100644 --- a/docs/sdk/configuration.rst +++ b/docs/sdk/configuration.rst @@ -76,10 +76,10 @@ OTLP/HTTP. The source is available :scm_web:`here - batch: exporter: otlp_http: - endpoint: https://api.honeycomb.io/v1/traces + endpoint: https://otlp.example.com:4318/v1/traces headers: - - name: x-honeycomb-team - value: ${HONEYCOMB_API_KEY} + - name: api-key + value: ${OTLP_API_KEY} sampler: parent_based: root: @@ -91,20 +91,20 @@ OTLP/HTTP. The source is available :scm_web:`here interval: 60000 exporter: otlp_http: - endpoint: https://api.honeycomb.io/v1/metrics + endpoint: https://otlp.example.com:4318/v1/metrics headers: - - name: x-honeycomb-team - value: ${HONEYCOMB_API_KEY} + - name: api-key + value: ${OTLP_API_KEY} logger_provider: processors: - batch: exporter: otlp_http: - endpoint: https://api.honeycomb.io/v1/logs + endpoint: https://otlp.example.com:4318/v1/logs headers: - - name: x-honeycomb-team - value: ${HONEYCOMB_API_KEY} + - name: api-key + value: ${OTLP_API_KEY} Environment variable substitution ---------------------------------- @@ -118,7 +118,7 @@ is parsed. * ``${VAR:-default}`` — replaced with ``VAR`` if set, otherwise ``default``. * ``$$`` — a literal ``$``. -In the example above, ``${HONEYCOMB_API_KEY}`` is required, while +In the example above, ``${OTLP_API_KEY}`` is required, while ``${DEPLOYMENT_ENVIRONMENT:-development}`` falls back to ``development`` when unset. From ada6a5a0cecb0786c5b8126789db61830f5847bf Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Tue, 16 Jun 2026 16:08:04 +0100 Subject: [PATCH 3/3] docs: use example.com endpoint so link check ignores it The check-links CI resolves new URLs; otlp.example.com is not covered by the existing ignore patterns. Use the apex example.com placeholder, which the check_links_config.json ignore list already matches. --- docs/sdk/configuration.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdk/configuration.rst b/docs/sdk/configuration.rst index dad5a5c1c0f..340348a5a0f 100644 --- a/docs/sdk/configuration.rst +++ b/docs/sdk/configuration.rst @@ -76,7 +76,7 @@ OTLP/HTTP. The source is available :scm_web:`here - batch: exporter: otlp_http: - endpoint: https://otlp.example.com:4318/v1/traces + endpoint: https://example.com:4318/v1/traces headers: - name: api-key value: ${OTLP_API_KEY} @@ -91,7 +91,7 @@ OTLP/HTTP. The source is available :scm_web:`here interval: 60000 exporter: otlp_http: - endpoint: https://otlp.example.com:4318/v1/metrics + endpoint: https://example.com:4318/v1/metrics headers: - name: api-key value: ${OTLP_API_KEY} @@ -101,7 +101,7 @@ OTLP/HTTP. The source is available :scm_web:`here - batch: exporter: otlp_http: - endpoint: https://otlp.example.com:4318/v1/logs + endpoint: https://example.com:4318/v1/logs headers: - name: api-key value: ${OTLP_API_KEY}