Skip to content

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

Open
MikeGoldsmith wants to merge 7 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 7 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.

- replace _sdk_default_attributes() with _DEFAULT_RESOURCE from resources module
- move _coerce_bool into dispatch tables for both scalar and array bool types,
  fixing a bug where bool_array with string values like "false" would coerce
  incorrectly via plain bool() (non-empty string -> True)
- add test for bool_array with string values to cover the bug

Assisted-by: Claude Sonnet 4.6
seen_types.add(type(propagator))
propagators.append(propagator)

# Process structured composite list
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the structured propagator list also support entrypoints?

Copy link
Member Author

Choose a reason for hiding this comment

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

The structured composite list is intentionally limited to the four types defined in the config schema (tracecontext, baggage, b3, b3multi) — the schema enforces maxProperties: 1 with fixed property names, so there's no way to specify an unknown third-party propagator via that path. For anything outside those four, composite_list (the comma-separated string) is the right mechanism, and that does use entry points. So I don't think we need entry point support in the structured path.

…erge

- collapse _SCALAR_COERCIONS and _ARRAY_COERCIONS into a single _COERCIONS
  dict using an _array() factory, reducing _coerce_attribute_value to two lines
- process attributes_list before attributes so explicit attributes naturally
  overwrite list entries without needing an explicit guard

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.

Thanks, LGTM once suggestions are addressed (I added a typing suggestion).

return bool(value)


def _array(coerce: object) -> object:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def _array(coerce: object) -> object:
def _array(coerce: Callable) -> Callable:

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.

3 participants