Skip to content

feat(config): add resource and propagator creation from declarative config#4979

Open
MikeGoldsmith wants to merge 3 commits intoopen-telemetry:mainfrom
MikeGoldsmith:mike/config-resource-propagator
Open

feat(config): add resource and propagator creation from declarative config#4979
MikeGoldsmith wants to merge 3 commits intoopen-telemetry:mainfrom
MikeGoldsmith:mike/config-resource-propagator

Conversation

@MikeGoldsmith
Copy link
Member

@MikeGoldsmith MikeGoldsmith commented Mar 13, 2026

Description

Implements step 3 of the declarative configuration work (see below), resource and propagator creation from a parsed config file.

Adds:

  • create_resource(config) — builds an SDK Resource from the declarative config model without reading OTEL_RESOURCE_ATTRIBUTES or running any resource detectors (matches Java/JS SDK behavior). Starts from SDK telemetry defaults (telemetry.sdk.*), merges attributes (with AttributeType coercion) and attributes_list (URL-decoded, lower priority), and adds service.name=unknown_service if not specified.
  • create_propagator(config) — builds a CompositePropagator from the config's composite list and/or composite_list string. Deduplicates by propagator type. Returns an empty CompositePropagator (noop) when no propagator is configured.
  • configure_propagator(config) — calls set_global_textmap to override Python's default env-var-based propagator setup.
  • ConfigurationError moved to _exceptions.py to break a circular import introduced when file/__init__.py re-exports the new functions.

All functions are exported from opentelemetry.sdk._configuration.file.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

43 new unit tests covering:

  • All AttributeType coercions (string, bool, int, double, and array variants)
  • attributes_list parsing: priority vs explicit attributes, URL decoding, = in values, invalid pairs
  • schema_url passthrough
  • OTEL_RESOURCE_ATTRIBUTES env var is NOT read
  • All four built-in propagators (tracecontext, baggage, b3, b3multi)
  • composite + composite_list merging and deduplication
  • none and empty entries in composite_list skipped
  • Missing entry point raises ConfigurationError
  • configure_propagator calls set_global_textmap

Does This PR Require a Contrib Repo Change?

  • No.

Checklist:

  • Followed the style guidelines of this project
  • Changelogs have been updated
  • Unit tests have been added
  • Documentation has been updated

Assisted-by: Claude Sonnet 4.6

Implements create_resource() and create_propagator()/configure_propagator()
for the declarative file configuration. Resource creation does not read
OTEL_RESOURCE_ATTRIBUTES or run any detectors (matches Java/JS SDK behavior).
Propagator configuration always calls set_global_textmap to override Python's
default tracecontext+baggage, setting a noop CompositePropagator when no
propagator is configured.

Assisted-by: Claude Sonnet 4.6
@MikeGoldsmith MikeGoldsmith requested a review from a team as a code owner March 13, 2026 13:11
@MikeGoldsmith MikeGoldsmith moved this to Ready for review in Python PR digest Mar 13, 2026
Assisted-by: Claude Sonnet 4.6
- _resource.py: refactor _coerce_attribute_value to dispatch table to
  avoid too-many-return-statements; fix short variable names k/v ->
  attr_key/attr_val; fix return type of _sdk_default_attributes to
  dict[str, str] to satisfy pyright
- _propagator.py: rename short variable names e -> exc, p -> propagator
- test_resource.py: move imports to top level; split TestCreateResource
  (25 methods) into three focused classes to satisfy too-many-public-methods
- test_propagator.py: add pylint disable for protected-access

Assisted-by: Claude Sonnet 4.6
Copy link
Member

@pmcollins pmcollins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Minor comments below.


def _sdk_default_attributes() -> dict[str, str]:
"""Return the SDK telemetry attributes (equivalent to Java's Resource.getDefault())."""
return {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this these same values are passed into a Resource as

_DEFAULT_RESOURCE = Resource(
    {
        TELEMETRY_SDK_LANGUAGE: "python",
        TELEMETRY_SDK_NAME: "opentelemetry",
        TELEMETRY_SDK_VERSION: _OPENTELEMETRY_SDK_VERSION,
    }
)

in opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py
Might be nice to share this definition.

return value


def _parse_attributes_list(attributes_list: str) -> dict[str, str]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like comma delimited k=v parsing is done in OTELResourceDetector as well. Can they be consolidated?

if attr_type is None:
return value
if attr_type == AttributeType.bool:
return _coerce_bool(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we're treating bool as a special case, but only for scalars. For arrays, we have bool() in the dispatch table (which may not give us what we want). Maybe _coerce_bool could go into the dispatch table for both cases and the if attr_type == AttributeType.bool carveout could be removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

2 participants