Skip to content

oss_24_declarative_config_present_null_defaults - #34

Closed
ocelotl wants to merge 2 commits into
mainfrom
oss_24_declarative_config_present_null_defaults
Closed

oss_24_declarative_config_present_null_defaults#34
ocelotl wants to merge 2 commits into
mainfrom
oss_24_declarative_config_present_null_defaults

Conversation

@ocelotl

@ocelotl ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Closes #31

Declarative config: a present-but-null component (e.g. console: with no value) now builds that component with defaults instead of raising ConfigurationError; present-null is carried through conversion distinctly from an absent key (Linear OSS-24, finding L1).

Validation: scope contained to opentelemetry-configuration + changelog; full package suite 369 passed.

Linear issue: https://linear.app/dash0/issue/OSS-24/l1-declarative-config-present-but-null-components-fail-instead-of

@ocelotl

ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

🔒 Internal (dash0) — not for upstream.

@ocelotl

ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

📣 Public-facing draft — to be used for the upstream PR in open-telemetry/opentelemetry-python. No internal references; copy verbatim.

Title: Fix declarative config present-but-null components to build with defaults

What

Make a present-but-null component value in declarative configuration build that component with defaults, instead of raising ConfigurationError.

Why

A present-but-null value (e.g. console: with no value) mapped to None during dict-to-dataclass conversion, indistinguishable from an absent key. Component factories select with value is not None, so a present-null component was treated as "not configured" and raised ConfigurationError.

Spec

configuration/sdk.md requires parsing to distinguish a missing key from a present-null one, and a present-null component MUST be created with all defaults (matching Java and Go, which bind the raw node and construct with defaults).

How

_convert_value is only invoked for keys actually present in the parsed mapping — absent keys fall through to dataclass field defaults — so a None value there always means present-null. It is now carried through as:

  • a defaults-only dataclass instance for dataclass-typed fields (e.g. otlp_http:OtlpHttpExporter() with all fields None, so the exporter reads its own defaults / env vars),
  • an empty mapping for mapping-alias fields (e.g. the console exporter, typed dict[str, Any] | None), so the selecting factory still fires,
  • None for primitives.
    Absent keys remain None, preserving "not configured" semantics. No factory-selection changes needed.

Tests

New unit tests in test_conversion.py (present-null dataclass → defaults instance; present-null mapping-alias console{}; present-null primitive → None; absent → None; populated still converts) and factory-level tests in test_tracer_provider.py (present-null console builds a ConsoleSpanExporter; absent exporter type still raises). Full package suite: 369 passed.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

This PR has been automatically marked as stale because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 days of this comment.
If you're still working on this, please add a comment or push new commits.

@github-actions github-actions Bot added the Stale label Aug 6, 2026
ocelotl added 2 commits August 7, 2026 15:55
…ults

A present-but-null YAML value (e.g. `console:` with no value) previously
mapped to `None` during dict-to-dataclass conversion, making it
indistinguishable from an absent key. Component factories select on
`value is not None`, so a present-null component raised a
ConfigurationError instead of building the component with defaults.

The configuration spec requires parsing to distinguish a missing key from
a present-null one, and a present-null component MUST be created with all
defaults.

Because `_convert_value` is only invoked for keys that are actually present
(absent keys fall through to dataclass field defaults), a `None` value there
always means present-null. It is now carried through as:
- a defaults-only dataclass instance for dataclass-typed fields,
- an empty mapping for mapping-alias fields (e.g. the console exporter),
- `None` for primitives (already their use-default value).

Absent keys remain `None`, preserving 'not configured' semantics.
@ocelotl
ocelotl force-pushed the oss_24_declarative_config_present_null_defaults branch from 61009e8 to 2c4b7a3 Compare August 7, 2026 20:57
@ocelotl

ocelotl commented Aug 7, 2026

Copy link
Copy Markdown
Owner Author

Closing as superseded by upstream. This PR addressed OSS-24 / L1 (declarative-config present-but-null components should build with defaults instead of raising). Upstream open-telemetry#5454 ("treat present-null config value as empty mapping", commit 4ea521a73) has since implemented exactly this in _conversion.py::_convert_value (coerces present-null to {} for dict-typed nodes and empty-constructible dataclasses, with the required-field guard). This branch's remaining diff is tests + changelog only — the production behavior is already upstream. No longer needed.

@ocelotl ocelotl closed this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

oss_24_declarative_config_present_null_defaults

1 participant