Skip to content

Commit 4beac07

Browse files
committed
refactor: rename _instrumentation to instrumentation, use from-imports, expand slash-normalization comment
1 parent 0e8761d commit 4beac07

4 files changed

Lines changed: 45 additions & 42 deletions

File tree

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

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@
1111

1212
from __future__ import annotations
1313

14-
import dataclasses
15-
import enum
16-
import types
17-
import typing
1814
from collections.abc import Mapping
19-
from typing import Any, TypeVar, get_args, get_origin
15+
from dataclasses import fields, is_dataclass
16+
from enum import Enum
17+
from types import UnionType
18+
from typing import Any, TypeVar, Union, get_args, get_origin, get_type_hints
2019

2120
_T = TypeVar("_T")
2221

@@ -27,7 +26,7 @@ def _unwrap_optional(type_hint: Any) -> Any:
2726
Returns the unwrapped type, or the original hint if not a union with None.
2827
"""
2928
origin = get_origin(type_hint)
30-
if origin is types.UnionType or origin is typing.Union:
29+
if origin is UnionType or origin is Union:
3130
non_none = [t for t in get_args(type_hint) if t is not type(None)]
3231
if len(non_none) == 1:
3332
return non_none[0]
@@ -58,15 +57,15 @@ def _convert_value(value: Any, type_hint: Any) -> Any:
5857
# Direct dataclass type — recurse
5958
if (
6059
isinstance(unwrapped, type)
61-
and dataclasses.is_dataclass(unwrapped)
60+
and is_dataclass(unwrapped)
6261
and isinstance(value, dict)
6362
):
6463
return _dict_to_dataclass(value, unwrapped)
6564

6665
# Enum type — coerce string/value to the Enum member
6766
if (
6867
isinstance(unwrapped, type)
69-
and issubclass(unwrapped, enum.Enum)
68+
and issubclass(unwrapped, Enum)
7069
and not isinstance(value, unwrapped)
7170
):
7271
return unwrapped(value)
@@ -90,21 +89,24 @@ def _dict_to_dataclass(data: Mapping[str, Any], cls: type[_T]) -> _T:
9089
Raises:
9190
TypeError: If ``cls`` is not a dataclass type.
9291
"""
93-
if not dataclasses.is_dataclass(cls):
92+
if not is_dataclass(cls):
9493
raise TypeError(f"{cls.__name__} is not a dataclass")
9594

9695
# Annotated as ``dict[str, Any]`` so astroid stops tracing into
97-
# ``typing.get_type_hints`` — under pylint 3.x that path leads into
96+
# ``get_type_hints`` — under pylint 3.x that path leads into
9897
# Python 3.14's ``annotationlib`` (which uses t-strings) and crashes.
99-
hints: dict[str, Any] = dict(
100-
typing.get_type_hints(cls, include_extras=False)
101-
)
102-
known_fields = {f.name for f in dataclasses.fields(cls)}
98+
hints: dict[str, Any] = dict(get_type_hints(cls, include_extras=False))
99+
known_fields = {f.name for f in fields(cls)}
103100
kwargs: dict[str, Any] = {}
104101

105102
for key, value in data.items():
106-
# Schema keys like "otlp_file/development" use "/" as a namespace
107-
# separator; Python field names use "_". Normalise before lookup.
103+
# The OTel configuration schema uses "/" as a namespace separator for
104+
# development/experimental features (e.g. "otlp_file/development",
105+
# "instrumentation/development"). Python identifiers cannot contain
106+
# "/", so the corresponding dataclass fields use "_" instead (e.g.
107+
# "otlp_file_development"). Without this normalisation the key would
108+
# not match any known field and would fall through to
109+
# additional_properties, causing the factory lookup to fail silently.
108110
field_key = key.replace("/", "_")
109111
if field_key in known_fields:
110112
type_hint = hints.get(field_key)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
)
2121
from opentelemetry.sdk._configuration._propagator import configure_propagator
2222
from opentelemetry.sdk._configuration._resource import create_resource
23-
from opentelemetry.sdk._configuration._instrumentation import (
23+
from opentelemetry.sdk._configuration.instrumentation import (
2424
configure_instrumentation,
2525
)
2626
from opentelemetry.sdk._configuration._tracer_provider import (

opentelemetry-sdk/src/opentelemetry/sdk/_configuration/_instrumentation.py renamed to opentelemetry-sdk/src/opentelemetry/sdk/_configuration/instrumentation.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,39 @@
33

44
from __future__ import annotations
55

6-
import dataclasses
7-
import logging
6+
from dataclasses import fields
7+
from logging import getLogger
88

99
from opentelemetry.sdk._configuration._common import load_entry_point
1010
from opentelemetry.sdk._configuration._conversion import _dict_to_dataclass
1111
from opentelemetry.sdk._configuration._exceptions import ConfigurationError
1212
from opentelemetry.sdk._configuration.models import ExperimentalInstrumentation
1313

14-
_logger = logging.getLogger(__name__)
14+
_logger = getLogger(__name__)
1515

1616

1717
def configure_instrumentation(
18-
config: ExperimentalInstrumentation | None,
18+
configuration: ExperimentalInstrumentation | None,
1919
) -> None:
2020
"""Activate instrumentors listed under ``instrumentation/development.python``.
2121
22-
For each entry in ``config.python`` the matching ``opentelemetry_instrumentor``
23-
entry point is loaded. If the instrumentor class exposes a
24-
``config_dataclass`` attribute, the raw options are validated through
25-
``_dict_to_dataclass`` before being forwarded to ``instrument()``.
26-
An ``enabled: false`` value suppresses instrumentation without raising.
22+
For each entry in ``configuration.python`` the matching
23+
``opentelemetry_instrumentor`` entry point is loaded. If the instrumentor
24+
class exposes a ``config_dataclass`` attribute, the raw options are
25+
validated through ``_dict_to_dataclass`` before being forwarded to
26+
``instrument()``. An ``enabled: false`` value suppresses instrumentation
27+
without raising.
2728
2829
Absent or unknown entry points are logged as warnings; runtime errors from
2930
an instrumentor are logged as exceptions. Neither stops the remaining
3031
instrumentors from being applied.
3132
"""
32-
if config is None or config.python is None:
33+
if configuration is None or configuration.python is None:
3334
return
3435

35-
for name, opts in config.python.items():
36-
opts = dict(opts)
37-
if not opts.pop("enabled", True):
36+
for name, options in configuration.python.items():
37+
options = dict(options)
38+
if not options.pop("enabled", True):
3839
_logger.debug(
3940
"Instrumentation '%s' is disabled in declarative config; skipping",
4041
name,
@@ -43,15 +44,15 @@ def configure_instrumentation(
4344

4445
try:
4546
cls = load_entry_point("opentelemetry_instrumentor", name)
46-
config_cls = getattr(cls, "config_dataclass", None)
47-
if config_cls is not None:
48-
config_obj = _dict_to_dataclass(opts, config_cls)
49-
opts = {
47+
configuration_cls = getattr(cls, "config_dataclass", None)
48+
if configuration_cls is not None:
49+
configuration_obj = _dict_to_dataclass(options, configuration_cls)
50+
options = {
5051
f.name: v
51-
for f in dataclasses.fields(config_obj)
52-
if (v := getattr(config_obj, f.name)) is not None
52+
for f in fields(configuration_obj)
53+
if (v := getattr(configuration_obj, f.name)) is not None
5354
}
54-
cls().instrument(**opts)
55+
cls().instrument(**options)
5556
_logger.debug("Instrumented '%s' via declarative config", name)
5657
except ConfigurationError as exc:
5758
_logger.warning(

opentelemetry-sdk/tests/_configuration/test_instrumentation.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
from unittest.mock import MagicMock, patch
88

99
from opentelemetry.sdk._configuration._exceptions import ConfigurationError
10-
from opentelemetry.sdk._configuration._instrumentation import (
10+
from opentelemetry.sdk._configuration.instrumentation import (
1111
configure_instrumentation,
1212
)
1313
from opentelemetry.sdk._configuration.models import ExperimentalInstrumentation
1414

15-
_LOAD_EP = "opentelemetry.sdk._configuration._instrumentation.load_entry_point"
15+
_LOAD_EP = "opentelemetry.sdk._configuration.instrumentation.load_entry_point"
1616

1717

1818
def _make_instrumentor_class(instance, config_dataclass=None):
@@ -32,7 +32,7 @@ def test_none_python_is_noop(self):
3232
@patch(_LOAD_EP, side_effect=ConfigurationError("not found"))
3333
def test_unknown_instrumentor_logs_warning(self, _mock_load):
3434
with self.assertLogs(
35-
"opentelemetry.sdk._configuration._instrumentation",
35+
"opentelemetry.sdk._configuration.instrumentation",
3636
level=logging.WARNING,
3737
) as cm:
3838
configure_instrumentation(
@@ -136,7 +136,7 @@ def _side_effect(_group, _name):
136136
mock_load.side_effect = _side_effect
137137

138138
with self.assertLogs(
139-
"opentelemetry.sdk._configuration._instrumentation",
139+
"opentelemetry.sdk._configuration.instrumentation",
140140
level=logging.ERROR,
141141
):
142142
configure_instrumentation(
@@ -200,7 +200,7 @@ class StrictConfig:
200200
)
201201

202202
with self.assertLogs(
203-
"opentelemetry.sdk._configuration._instrumentation",
203+
"opentelemetry.sdk._configuration.instrumentation",
204204
level=logging.ERROR,
205205
):
206206
configure_instrumentation(

0 commit comments

Comments
 (0)