Skip to content

Commit d086833

Browse files
aman-panjwanixrmx
andauthored
feat(config): wire id_generator from declarative configuration to TracerProvider (#5363)
* feat(config): wire id_generator from declarative configuration to TracerProvider * add changelog fragment * fix: add _additional_properties decorator to IdGenerator model * fix: rename changelog to .added, pass plugin kwargs, add hasattr check * fix: apply ruff formatting * fix: apply ruff formatting * Apply suggestion from @xrmx * Apply suggestion from @xrmx --------- Co-authored-by: Riccardo Magliocchetti <riccardo.magliocchetti@gmail.com>
1 parent 5cda269 commit d086833

3 files changed

Lines changed: 86 additions & 0 deletions

File tree

.changelog/5363.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`opentelemetry-sdk`: wire id_generator from declarative configuration to TracerProvider

opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_tracer_provider.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
from opentelemetry.sdk._configuration.models import (
2626
ExperimentalOtlpFileExporter as ExperimentalOtlpFileExporterConfig,
2727
)
28+
from opentelemetry.sdk._configuration.models import (
29+
IdGenerator as IdGeneratorConfig,
30+
)
2831
from opentelemetry.sdk._configuration.models import (
2932
OtlpGrpcExporter as OtlpGrpcExporterConfig,
3033
)
@@ -84,6 +87,7 @@
8487
SimpleSpanProcessor,
8588
SpanExporter,
8689
)
90+
from opentelemetry.sdk.trace.id_generator import IdGenerator, RandomIdGenerator
8791
from opentelemetry.sdk.trace.sampling import (
8892
ALWAYS_OFF,
8993
ALWAYS_ON,
@@ -348,6 +352,26 @@ def _create_sampler(config: SamplerConfig) -> Sampler:
348352
)
349353

350354

355+
def _create_id_generator(config: IdGeneratorConfig) -> IdGenerator:
356+
"""Create an IdGenerator from config.
357+
358+
Built-in ``random`` resolves to ``RandomIdGenerator``; unknown names
359+
load from the ``opentelemetry_id_generator`` entry point group (the
360+
same group ``OTEL_PYTHON_ID_GENERATOR`` uses today).
361+
"""
362+
if config.random is not None:
363+
return RandomIdGenerator()
364+
if config.additional_properties:
365+
name, plugin_config = next(iter(config.additional_properties.items()))
366+
return load_entry_point("opentelemetry_id_generator", name)(
367+
**(plugin_config or {})
368+
)
369+
raise ConfigurationError(
370+
"No id_generator type specified in config. "
371+
"Supported built-in types: random."
372+
)
373+
374+
351375
def _create_parent_based_sampler(config: ParentBasedSamplerConfig) -> Sampler:
352376
"""Create a ParentBased sampler from config, applying SDK defaults for absent delegates."""
353377
root = (
@@ -431,6 +455,11 @@ def create_tracer_provider(
431455
if config is not None and config.sampler is not None
432456
else _DEFAULT_SAMPLER
433457
)
458+
id_generator = (
459+
_create_id_generator(config.id_generator)
460+
if config is not None and config.id_generator is not None
461+
else None
462+
)
434463
span_limits = (
435464
_create_span_limits(config.limits)
436465
if config is not None and config.limits is not None
@@ -447,6 +476,7 @@ def create_tracer_provider(
447476
resource=resource,
448477
sampler=sampler,
449478
span_limits=span_limits,
479+
id_generator=id_generator,
450480
)
451481

452482
if config is not None:

opentelemetry-sdk/tests/_configuration/test_tracer_provider.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
from opentelemetry.sdk._configuration.models import (
4343
ExperimentalSpanParent as SpanParentConfig,
4444
)
45+
from opentelemetry.sdk._configuration.models import (
46+
IdGenerator as IdGeneratorConfig,
47+
)
4548
from opentelemetry.sdk._configuration.models import (
4649
OtlpGrpcExporter as OtlpGrpcExporterConfig,
4750
)
@@ -82,6 +85,7 @@
8285
ConsoleSpanExporter,
8386
SimpleSpanProcessor,
8487
)
88+
from opentelemetry.sdk.trace.id_generator import RandomIdGenerator
8589
from opentelemetry.sdk.trace.sampling import (
8690
ALWAYS_OFF,
8791
ALWAYS_ON,
@@ -852,3 +856,54 @@ def test_absent_limits_do_not_read_env_vars(self):
852856
provider = self._create_with_limits(SpanLimitsConfig())
853857
self.assertEqual(provider._span_limits.max_span_attributes, 128)
854858
self.assertEqual(provider._span_limits.max_events, 128)
859+
860+
861+
class TestCreateIdGenerator(unittest.TestCase):
862+
"""Tests for _create_id_generator and id_generator wiring in create_tracer_provider."""
863+
864+
@staticmethod
865+
def _make_provider(id_generator_config):
866+
return create_tracer_provider(
867+
TracerProviderConfig(
868+
processors=[], id_generator=id_generator_config
869+
)
870+
)
871+
872+
def test_absent_id_generator_uses_sdk_default(self):
873+
"""When id_generator is omitted, the SDK's default RandomIdGenerator is used."""
874+
provider = create_tracer_provider(TracerProviderConfig(processors=[]))
875+
self.assertIsInstance(provider.id_generator, RandomIdGenerator)
876+
877+
def test_builtin_random_id_generator(self):
878+
"""Built-in 'random' id_generator resolves to RandomIdGenerator."""
879+
provider = self._make_provider(IdGeneratorConfig(random={}))
880+
self.assertIsInstance(provider.id_generator, RandomIdGenerator)
881+
882+
def test_plugin_id_generator_loaded_via_entry_point(self):
883+
"""Unknown id_generator name is loaded from opentelemetry_id_generator entry point group."""
884+
mock_generator = MagicMock()
885+
mock_class = MagicMock(return_value=mock_generator)
886+
with patch(
887+
"opentelemetry.sdk._configuration._common.entry_points",
888+
return_value=[MagicMock(**{"load.return_value": mock_class})],
889+
):
890+
# pylint: disable=unexpected-keyword-arg
891+
provider = self._make_provider(
892+
IdGeneratorConfig(my_custom_generator={})
893+
)
894+
self.assertIs(provider.id_generator, mock_generator)
895+
896+
def test_unknown_id_generator_raises_configuration_error(self):
897+
"""Unknown id_generator name with no matching entry point raises ConfigurationError."""
898+
with patch(
899+
"opentelemetry.sdk._configuration._common.entry_points",
900+
return_value=[],
901+
):
902+
with self.assertRaises(ConfigurationError):
903+
# pylint: disable=unexpected-keyword-arg
904+
self._make_provider(IdGeneratorConfig(no_such_generator={}))
905+
906+
def test_empty_id_generator_raises_configuration_error(self):
907+
"""Empty IdGenerator config (no type specified) raises ConfigurationError."""
908+
with self.assertRaises(ConfigurationError):
909+
self._make_provider(IdGeneratorConfig())

0 commit comments

Comments
 (0)