Skip to content

feat(config): add additionalProperties support to generated config models#5131

Open
MikeGoldsmith wants to merge 8 commits intoopen-telemetry:mainfrom
MikeGoldsmith:mike/config-additional-properties-support
Open

feat(config): add additionalProperties support to generated config models#5131
MikeGoldsmith wants to merge 8 commits intoopen-telemetry:mainfrom
MikeGoldsmith:mike/config-additional-properties-support

Conversation

@MikeGoldsmith
Copy link
Copy Markdown
Member

@MikeGoldsmith MikeGoldsmith commented Apr 20, 2026

Description

Adds support for JSON Schema additionalProperties to the generated config dataclasses. This is the foundation for plugin/custom component loading in declarative file configuration — unknown component names (e.g. my_custom_sampler, my_custom_exporter) can now flow through typed dataclasses without being silently dropped.

Problem

The OTel configuration JSON schema defines additionalProperties on 12 types (Sampler, SpanExporter, TextMapPropagator, ExperimentalResourceDetector, LogRecordExporter, PushMetricExporter, etc.) to allow plugin component names as keys. However, datamodel-codegen ignores additionalProperties when generating plain Python dataclasses — there's no stdlib mechanism for it. Unknown kwargs are rejected by the dataclass __init__.

Solution

A custom datamodel-codegen template (opentelemetry-sdk/codegen/dataclass.jinja2) conditionally adds two things to affected classes:

  1. @_additional_properties_support decorator — wraps the dataclass __init__ to route unknown kwargs into an additional_properties instance attribute instead of raising TypeError
  2. additional_properties: ClassVar[dict[str, Any]] annotation — satisfies type checkers without creating a dataclass field, so additional_properties doesn't appear in __init__ signature, dataclasses.fields(), asdict(), or repr()

The decorator preserves the original inspect.signature() (for IDE autocompletion) and appends **kwargs to signal extras are accepted.

How it works

The template checks additionalPropertiesType, a context variable that datamodel-codegen sets for schema types where additionalProperties is a type object (e.g. {"type": ["object", "null"]}). This is how the OTel schema defines it for plugin-capable types.

Usage

from opentelemetry.sdk._configuration.models import Sampler

# Known sampler — works as before
s = Sampler(always_on={})
assert s.always_on == {}
assert s.additional_properties == {}

# Plugin sampler — unknown name captured
s = Sampler(my_custom_sampler={"ratio": 0.5})
assert s.additional_properties == {"my_custom_sampler": {"ratio": 0.5}}

Codegen

No changes to the codegen workflow — tox -e generate-config-from-jsonschema picks up the custom template via the custom-template-dir config in pyproject.toml.

Tests

  • TestAdditionalPropertiesSupport — 5 unit tests for the decorator (known fields, unknown fields, mixed, empty, signature preservation)
  • TestGeneratedModelsHaveAdditionalProperties — 6 regression tests verifying the key generated models accept unknown kwargs (guards against datamodel-codegen changing how it passes the template variable)

Schema types with additionalProperties (Sampler, SpanExporter,
TextMapPropagator, ExperimentalResourceDetector, etc.) now capture
unknown keyword arguments in an additional_properties dict field.
This enables plugin/custom component names to flow through typed
dataclasses without modifying the codegen tool.

Implementation:
- _additional_properties_support decorator in _common.py wraps the
  dataclass __init__ to route unknown kwargs into additional_properties
- Custom dataclass.jinja2 template for datamodel-codegen conditionally
  applies the decorator and field when additionalPropertiesType is set
- pyproject.toml updated with custom-template-dir and additional-imports
- models.py regenerated via tox -e generate-config-from-jsonschema

Assisted-by: Claude Opus 4.6
@MikeGoldsmith MikeGoldsmith moved this to Ready for review in Python PR digest Apr 20, 2026
@MikeGoldsmith MikeGoldsmith added the config Issues and PRs related to implementing Declarative Config label Apr 20, 2026
…kwargs

- Replace object.__setattr__ with plain self.additional_properties = extra
  (no frozen dataclasses, simpler and more Pythonic)
- Add pylint disable=unexpected-keyword-arg on test lines that intentionally
  pass unknown kwargs to verify the decorator captures them
- Add comment explaining setattr usage for __signature__ (pyright workaround)

Assisted-by: Claude Opus 4.6
Comment thread opentelemetry-sdk/codegen/dataclass.jinja2 Outdated
@@ -1 +1 @@
# SDK File Configuration
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Something that I've been thinking about is if we want file configuration to be its own package entirely. I'm not sure if you have measured the code size yet, but I would imagine that as more features are added, it won't be insignificant. It would be good to at least provide users the option to not install file-based configuration, perhaps in very simple/minimal environments.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I understand the concern, but I don't think we're adding too much bloat here. Also, if we move to a separate package, the user experience of "it just works" will be broken.

The models are generated at dev-time and source controlled. The deps to build the models (JSON schema and jinja template) won't be included in the dist package either.

I hope to unify the env var & file config paths to leverage these generated models if I can so they'll be useful for both scenarios.

Does that help?

…perties

ClassVar tells type checkers the attribute exists without creating a
dataclass field. This means additional_properties doesn't appear in
__init__ signature, dataclasses.fields(), asdict(), or repr() — only
schema-defined fields show up. The decorator sets it as a plain
instance attribute at runtime.

Assisted-by: Claude Opus 4.6
…s-support' into mike/config-additional-properties-support
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config Issues and PRs related to implementing Declarative Config

Projects

Status: Ready for review

Development

Successfully merging this pull request may close these issues.

2 participants