From b0bd1f3619f6098b65dfac25299324dd5bd1dd03 Mon Sep 17 00:00:00 2001 From: Aman Panjwani Date: Fri, 26 Jun 2026 20:54:20 +0530 Subject: [PATCH 1/3] feat(config): wire id_generator from declarative configuration to TracerProvider --- .../sdk/_configuration/_tracer_provider.py | 31 +++++++++++ .../_configuration/test_tracer_provider.py | 55 +++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py index f6c3a06c7f..ee7d73a962 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py @@ -10,6 +10,7 @@ _map_compression, _parse_headers, _parse_otlp_file_output_stream, + _resolve_component, load_entry_point, ) from opentelemetry.sdk._configuration._exceptions import ConfigurationError @@ -25,6 +26,9 @@ from opentelemetry.sdk._configuration.models import ( ExperimentalOtlpFileExporter as ExperimentalOtlpFileExporterConfig, ) +from opentelemetry.sdk._configuration.models import ( + IdGenerator as IdGeneratorConfig, +) from opentelemetry.sdk._configuration.models import ( OtlpGrpcExporter as OtlpGrpcExporterConfig, ) @@ -84,6 +88,7 @@ SimpleSpanProcessor, SpanExporter, ) +from opentelemetry.sdk.trace.id_generator import IdGenerator, RandomIdGenerator from opentelemetry.sdk.trace.sampling import ( ALWAYS_OFF, ALWAYS_ON, @@ -348,6 +353,26 @@ def _create_sampler(config: SamplerConfig) -> Sampler: ) +_ID_GENERATOR_REGISTRY: dict = { + "random": lambda _: RandomIdGenerator(), +} + + +def _create_id_generator(config: IdGeneratorConfig) -> IdGenerator: + """Create an IdGenerator from config. + + Built-in ``random`` resolves to ``RandomIdGenerator``; unknown names + load from the ``opentelemetry_id_generator`` entry point group (the + same group ``OTEL_PYTHON_ID_GENERATOR`` uses today). + """ + return _resolve_component( + config, + _ID_GENERATOR_REGISTRY, + "opentelemetry_id_generator", + "id_generator", + ) + + def _create_parent_based_sampler(config: ParentBasedSamplerConfig) -> Sampler: """Create a ParentBased sampler from config, applying SDK defaults for absent delegates.""" root = ( @@ -431,6 +456,11 @@ def create_tracer_provider( if config is not None and config.sampler is not None else _DEFAULT_SAMPLER ) + id_generator = ( + _create_id_generator(config.id_generator) + if config is not None and config.id_generator is not None + else None + ) span_limits = ( _create_span_limits(config.limits) if config is not None and config.limits is not None @@ -447,6 +477,7 @@ def create_tracer_provider( resource=resource, sampler=sampler, span_limits=span_limits, + id_generator=id_generator, ) if config is not None: diff --git a/opentelemetry-sdk/tests/_configuration/test_tracer_provider.py b/opentelemetry-sdk/tests/_configuration/test_tracer_provider.py index abac735fe4..e57acdc713 100644 --- a/opentelemetry-sdk/tests/_configuration/test_tracer_provider.py +++ b/opentelemetry-sdk/tests/_configuration/test_tracer_provider.py @@ -42,6 +42,9 @@ from opentelemetry.sdk._configuration.models import ( ExperimentalSpanParent as SpanParentConfig, ) +from opentelemetry.sdk._configuration.models import ( + IdGenerator as IdGeneratorConfig, +) from opentelemetry.sdk._configuration.models import ( OtlpGrpcExporter as OtlpGrpcExporterConfig, ) @@ -82,6 +85,7 @@ ConsoleSpanExporter, SimpleSpanProcessor, ) +from opentelemetry.sdk.trace.id_generator import RandomIdGenerator from opentelemetry.sdk.trace.sampling import ( ALWAYS_OFF, ALWAYS_ON, @@ -852,3 +856,54 @@ def test_absent_limits_do_not_read_env_vars(self): provider = self._create_with_limits(SpanLimitsConfig()) self.assertEqual(provider._span_limits.max_span_attributes, 128) self.assertEqual(provider._span_limits.max_events, 128) + + +class TestCreateIdGenerator(unittest.TestCase): + """Tests for _create_id_generator and id_generator wiring in create_tracer_provider.""" + + @staticmethod + def _make_provider(id_generator_config): + return create_tracer_provider( + TracerProviderConfig( + processors=[], id_generator=id_generator_config + ) + ) + + def test_absent_id_generator_uses_sdk_default(self): + """When id_generator is omitted, the SDK's default RandomIdGenerator is used.""" + provider = create_tracer_provider(TracerProviderConfig(processors=[])) + self.assertIsInstance(provider.id_generator, RandomIdGenerator) + + def test_builtin_random_id_generator(self): + """Built-in 'random' id_generator resolves to RandomIdGenerator.""" + provider = self._make_provider(IdGeneratorConfig(random={})) + self.assertIsInstance(provider.id_generator, RandomIdGenerator) + + def test_plugin_id_generator_loaded_via_entry_point(self): + """Unknown id_generator name is loaded from opentelemetry_id_generator entry point group.""" + mock_generator = MagicMock() + mock_class = MagicMock(return_value=mock_generator) + with patch( + "opentelemetry.sdk._configuration._common.entry_points", + return_value=[MagicMock(**{"load.return_value": mock_class})], + ): + # pylint: disable=unexpected-keyword-arg + provider = self._make_provider( + IdGeneratorConfig(my_custom_generator={}) + ) + self.assertIs(provider.id_generator, mock_generator) + + def test_unknown_id_generator_raises_configuration_error(self): + """Unknown id_generator name with no matching entry point raises ConfigurationError.""" + with patch( + "opentelemetry.sdk._configuration._common.entry_points", + return_value=[], + ): + with self.assertRaises(ConfigurationError): + # pylint: disable=unexpected-keyword-arg + self._make_provider(IdGeneratorConfig(no_such_generator={})) + + def test_empty_id_generator_raises_configuration_error(self): + """Empty IdGenerator config (no type specified) raises ConfigurationError.""" + with self.assertRaises(ConfigurationError): + self._make_provider(IdGeneratorConfig()) From 7079b9327088aee7b5e0a729bf7ff1dfec68fa67 Mon Sep 17 00:00:00 2001 From: Aman Panjwani Date: Fri, 26 Jun 2026 21:02:31 +0530 Subject: [PATCH 2/3] add changelog fragment --- .changelog/5363.changed | 1 + 1 file changed, 1 insertion(+) create mode 100644 .changelog/5363.changed diff --git a/.changelog/5363.changed b/.changelog/5363.changed new file mode 100644 index 0000000000..0874dd0375 --- /dev/null +++ b/.changelog/5363.changed @@ -0,0 +1 @@ +`opentelemetry-sdk`: wire id_generator from declarative configuration to TracerProvider From 39bbae857921cd14d36a4bfd90a8e628ba9154fa Mon Sep 17 00:00:00 2001 From: Aman Panjwani Date: Fri, 26 Jun 2026 21:22:49 +0530 Subject: [PATCH 3/3] fix: add _additional_properties decorator to IdGenerator model --- .../sdk/_configuration/_tracer_provider.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py index ee7d73a962..56c8dbd893 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py @@ -10,7 +10,6 @@ _map_compression, _parse_headers, _parse_otlp_file_output_stream, - _resolve_component, load_entry_point, ) from opentelemetry.sdk._configuration._exceptions import ConfigurationError @@ -353,11 +352,6 @@ def _create_sampler(config: SamplerConfig) -> Sampler: ) -_ID_GENERATOR_REGISTRY: dict = { - "random": lambda _: RandomIdGenerator(), -} - - def _create_id_generator(config: IdGeneratorConfig) -> IdGenerator: """Create an IdGenerator from config. @@ -365,11 +359,14 @@ def _create_id_generator(config: IdGeneratorConfig) -> IdGenerator: load from the ``opentelemetry_id_generator`` entry point group (the same group ``OTEL_PYTHON_ID_GENERATOR`` uses today). """ - return _resolve_component( - config, - _ID_GENERATOR_REGISTRY, - "opentelemetry_id_generator", - "id_generator", + if config.random is not None: + return RandomIdGenerator() + if config.additional_properties: + name = next(iter(config.additional_properties)) + return load_entry_point("opentelemetry_id_generator", name)() + raise ConfigurationError( + "No id_generator type specified in config. " + "Supported built-in types: random." )