Skip to content

Commit 6603a25

Browse files
authored
Merge branch 'main' into hectorhdzg/logrecrename
2 parents 15658f0 + 0e4cb44 commit 6603a25

File tree

26 files changed

+1880
-259
lines changed

26 files changed

+1880
-259
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
([#4649](https://github.com/open-telemetry/opentelemetry-python/pull/4649))
3636
- proto: relax protobuf version requirement to support v6
3737
([#4620](https://github.com/open-telemetry/opentelemetry-python/pull/4620))
38+
- Bump semantic-conventions to 1.36.0
39+
([#4669](https://github.com/open-telemetry/opentelemetry-python/pull/4669))
3840
- Set expected User-Agent in HTTP headers for grpc OTLP exporter
3941
([#4658](https://github.com/open-telemetry/opentelemetry-python/pull/4658))
4042
- Rename several classes from Log to LogRecord

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

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import os
2424
from abc import ABC, abstractmethod
2525
from os import environ
26-
from typing import Callable, Sequence, Type, Union
26+
from typing import Any, Callable, Mapping, Sequence, Type, Union
2727

2828
from typing_extensions import Literal
2929

@@ -94,10 +94,20 @@
9494

9595
_logger = logging.getLogger(__name__)
9696

97+
ExporterArgsMap = Mapping[
98+
Union[
99+
Type[SpanExporter],
100+
Type[MetricExporter],
101+
Type[MetricReader],
102+
Type[LogExporter],
103+
],
104+
Mapping[str, Any],
105+
]
106+
97107

98108
def _import_config_components(
99-
selected_components: list[str], entry_point_name: str
100-
) -> Sequence[tuple[str, object]]:
109+
selected_components: Sequence[str], entry_point_name: str
110+
) -> list[tuple[str, Type]]:
101111
component_implementations = []
102112

103113
for selected_component in selected_components:
@@ -182,7 +192,7 @@ def _get_exporter_entry_point(
182192

183193
def _get_exporter_names(
184194
signal_type: Literal["traces", "metrics", "logs"],
185-
) -> Sequence[str]:
195+
) -> list[str]:
186196
names = environ.get(_EXPORTER_ENV_BY_SIGNAL_TYPE.get(signal_type, ""))
187197

188198
if not names or names.lower().strip() == "none":
@@ -199,6 +209,7 @@ def _init_tracing(
199209
id_generator: IdGenerator | None = None,
200210
sampler: Sampler | None = None,
201211
resource: Resource | None = None,
212+
exporter_args_map: ExporterArgsMap | None = None,
202213
):
203214
provider = TracerProvider(
204215
id_generator=id_generator,
@@ -207,8 +218,9 @@ def _init_tracing(
207218
)
208219
set_tracer_provider(provider)
209220

221+
exporter_args_map = exporter_args_map or {}
210222
for _, exporter_class in exporters.items():
211-
exporter_args = {}
223+
exporter_args = exporter_args_map.get(exporter_class, {})
212224
provider.add_span_processor(
213225
BatchSpanProcessor(exporter_class(**exporter_args))
214226
)
@@ -219,12 +231,13 @@ def _init_metrics(
219231
str, Union[Type[MetricExporter], Type[MetricReader]]
220232
],
221233
resource: Resource | None = None,
234+
exporter_args_map: ExporterArgsMap | None = None,
222235
):
223236
metric_readers = []
224237

238+
exporter_args_map = exporter_args_map or {}
225239
for _, exporter_or_reader_class in exporters_or_readers.items():
226-
exporter_args = {}
227-
240+
exporter_args = exporter_args_map.get(exporter_or_reader_class, {})
228241
if issubclass(exporter_or_reader_class, MetricReader):
229242
metric_readers.append(exporter_or_reader_class(**exporter_args))
230243
else:
@@ -242,12 +255,14 @@ def _init_logging(
242255
exporters: dict[str, Type[LogRecordExporter]],
243256
resource: Resource | None = None,
244257
setup_logging_handler: bool = True,
258+
exporter_args_map: ExporterArgsMap | None = None,
245259
):
246260
provider = LoggerProvider(resource=resource)
247261
set_logger_provider(provider)
248262

263+
exporter_args_map = exporter_args_map or {}
249264
for _, exporter_class in exporters.items():
250-
exporter_args = {}
265+
exporter_args = exporter_args_map.get(exporter_class, {})
251266
provider.add_log_record_processor(
252267
BatchLogRecordProcessor(exporter_class(**exporter_args))
253268
)
@@ -334,22 +349,24 @@ def _import_exporters(
334349
return trace_exporters, metric_exporters, log_exporters
335350

336351

337-
def _import_sampler_factory(sampler_name: str) -> Callable[[str], Sampler]:
352+
def _import_sampler_factory(
353+
sampler_name: str,
354+
) -> Callable[[float | str | None], Sampler]:
338355
_, sampler_impl = _import_config_components(
339356
[sampler_name.strip()], _OTEL_SAMPLER_ENTRY_POINT_GROUP
340357
)[0]
341358
return sampler_impl
342359

343360

344-
def _import_sampler(sampler_name: str) -> Sampler | None:
361+
def _import_sampler(sampler_name: str | None) -> Sampler | None:
345362
if not sampler_name:
346363
return None
347364
try:
348365
sampler_factory = _import_sampler_factory(sampler_name)
349366
arg = None
350367
if sampler_name in ("traceidratio", "parentbased_traceidratio"):
351368
try:
352-
rate = float(os.getenv(OTEL_TRACES_SAMPLER_ARG))
369+
rate = float(os.getenv(OTEL_TRACES_SAMPLER_ARG, ""))
353370
except (ValueError, TypeError):
354371
_logger.warning(
355372
"Could not convert TRACES_SAMPLER_ARG to float. Using default value 1.0."
@@ -394,6 +411,7 @@ def _initialize_components(
394411
resource_attributes: Attributes | None = None,
395412
id_generator: IdGenerator | None = None,
396413
setup_logging_handler: bool | None = None,
414+
exporter_args_map: ExporterArgsMap | None = None,
397415
):
398416
if trace_exporter_names is None:
399417
trace_exporter_names = []
@@ -416,7 +434,7 @@ def _initialize_components(
416434
resource_attributes = {}
417435
# populate version if using auto-instrumentation
418436
if auto_instrumentation_version:
419-
resource_attributes[ResourceAttributes.TELEMETRY_AUTO_VERSION] = (
437+
resource_attributes[ResourceAttributes.TELEMETRY_AUTO_VERSION] = ( # type: ignore[reportIndexIssue]
420438
auto_instrumentation_version
421439
)
422440
# if env var OTEL_RESOURCE_ATTRIBUTES is given, it will read the service_name
@@ -428,8 +446,11 @@ def _initialize_components(
428446
id_generator=id_generator,
429447
sampler=sampler,
430448
resource=resource,
449+
exporter_args_map=exporter_args_map,
450+
)
451+
_init_metrics(
452+
metric_exporters, resource, exporter_args_map=exporter_args_map
431453
)
432-
_init_metrics(metric_exporters, resource)
433454
if setup_logging_handler is None:
434455
setup_logging_handler = (
435456
os.getenv(
@@ -439,7 +460,12 @@ def _initialize_components(
439460
.lower()
440461
== "true"
441462
)
442-
_init_logging(log_exporters, resource, setup_logging_handler)
463+
_init_logging(
464+
log_exporters,
465+
resource,
466+
setup_logging_handler,
467+
exporter_args_map=exporter_args_map,
468+
)
443469

444470

445471
class _BaseConfigurator(ABC):

opentelemetry-sdk/tests/test_configurator.py

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,9 @@ def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
178178

179179

180180
class DummyOTLPMetricExporter:
181-
def __init__(self, *args, **kwargs):
181+
def __init__(self, compression: str | None = None, *args, **kwargs):
182182
self.export_called = False
183+
self.compression = compression
183184

184185
def export(self, batch):
185186
self.export_called = True
@@ -202,12 +203,14 @@ def shutdown(self):
202203

203204

204205
class OTLPSpanExporter:
205-
pass
206+
def __init__(self, compression: str | None = None, *args, **kwargs):
207+
self.compression = compression
206208

207209

208210
class DummyOTLPLogExporter(LogRecordExporter):
209-
def __init__(self, *args, **kwargs):
211+
def __init__(self, compression: str | None = None, *args, **kwargs):
210212
self.export_called = False
213+
self.compression = compression
211214

212215
def export(self, batch):
213216
self.export_called = True
@@ -374,6 +377,20 @@ def test_trace_init_otlp(self):
374377
"my-otlp-test-service",
375378
)
376379

380+
def test_trace_init_exporter_uses_exporter_args_map(self):
381+
_init_tracing(
382+
{"otlp": OTLPSpanExporter},
383+
id_generator=RandomIdGenerator(),
384+
exporter_args_map={
385+
OTLPSpanExporter: {"compression": "gzip"},
386+
DummyMetricReaderPullExporter: {"compression": "no"},
387+
},
388+
)
389+
390+
provider = self.set_provider_mock.call_args[0][0]
391+
exporter = provider.processor.exporter
392+
self.assertEqual(exporter.compression, "gzip")
393+
377394
@patch.dict(environ, {OTEL_PYTHON_ID_GENERATOR: "custom_id_generator"})
378395
@patch("opentelemetry.sdk._configuration.IdGenerator", new=IdGenerator)
379396
@patch("opentelemetry.sdk._configuration.entry_points")
@@ -667,6 +684,20 @@ def test_logging_init_exporter(self):
667684
getLogger(__name__).error("hello")
668685
self.assertTrue(provider.processor.exporter.export_called)
669686

687+
def test_logging_init_exporter_uses_exporter_args_map(self):
688+
resource = Resource.create({})
689+
_init_logging(
690+
{"otlp": DummyOTLPLogExporter},
691+
resource=resource,
692+
exporter_args_map={
693+
DummyOTLPLogExporter: {"compression": "gzip"},
694+
DummyOTLPMetricExporter: {"compression": "no"},
695+
},
696+
)
697+
self.assertEqual(self.set_provider_mock.call_count, 1)
698+
provider = self.set_provider_mock.call_args[0][0]
699+
self.assertEqual(provider.processor.exporter.compression, "gzip")
700+
670701
@patch.dict(
671702
environ,
672703
{"OTEL_RESOURCE_ATTRIBUTES": "service.name=otlp-service"},
@@ -702,7 +733,9 @@ def test_logging_init_exporter_without_handler_setup(self):
702733
def test_logging_init_disable_default(self, logging_mock, tracing_mock):
703734
_initialize_components(auto_instrumentation_version="auto-version")
704735
self.assertEqual(tracing_mock.call_count, 1)
705-
logging_mock.assert_called_once_with(mock.ANY, mock.ANY, False)
736+
logging_mock.assert_called_once_with(
737+
mock.ANY, mock.ANY, False, exporter_args_map=None
738+
)
706739

707740
@patch.dict(
708741
environ,
@@ -716,7 +749,9 @@ def test_logging_init_disable_default(self, logging_mock, tracing_mock):
716749
def test_logging_init_enable_env(self, logging_mock, tracing_mock):
717750
with self.assertLogs(level=WARNING):
718751
_initialize_components(auto_instrumentation_version="auto-version")
719-
logging_mock.assert_called_once_with(mock.ANY, mock.ANY, True)
752+
logging_mock.assert_called_once_with(
753+
mock.ANY, mock.ANY, True, exporter_args_map=None
754+
)
720755
self.assertEqual(tracing_mock.call_count, 1)
721756

722757
@patch.dict(
@@ -799,6 +834,7 @@ def test_initialize_components_kwargs(
799834
},
800835
"id_generator": "TEST_GENERATOR",
801836
"setup_logging_handler": True,
837+
"exporter_args_map": {1: {"compression": "gzip"}},
802838
}
803839
_initialize_components(**kwargs)
804840

@@ -832,15 +868,18 @@ def test_initialize_components_kwargs(
832868
id_generator="TEST_GENERATOR",
833869
sampler="TEST_SAMPLER",
834870
resource="TEST_RESOURCE",
871+
exporter_args_map={1: {"compression": "gzip"}},
835872
)
836873
metrics_mock.assert_called_once_with(
837874
"TEST_METRICS_EXPORTERS_DICT",
838875
"TEST_RESOURCE",
876+
exporter_args_map={1: {"compression": "gzip"}},
839877
)
840878
logging_mock.assert_called_once_with(
841879
"TEST_LOG_EXPORTERS_DICT",
842880
"TEST_RESOURCE",
843881
True,
882+
exporter_args_map={1: {"compression": "gzip"}},
844883
)
845884

846885
def test_basicConfig_works_with_otel_handler(self):
@@ -970,6 +1009,20 @@ def test_metrics_init_pull_exporter(self):
9701009
reader = provider._sdk_config.metric_readers[0]
9711010
self.assertIsInstance(reader, DummyMetricReaderPullExporter)
9721011

1012+
def test_metrics_init_exporter_uses_exporter_args_map(self):
1013+
resource = Resource.create({})
1014+
_init_metrics(
1015+
{"otlp": DummyOTLPMetricExporter},
1016+
resource=resource,
1017+
exporter_args_map={
1018+
DummyOTLPMetricExporter: {"compression": "gzip"},
1019+
DummyMetricReaderPullExporter: {"compression": "no"},
1020+
},
1021+
)
1022+
provider = self.set_provider_mock.call_args[0][0]
1023+
reader = provider._sdk_config.metric_readers[0]
1024+
self.assertEqual(reader.exporter.compression, "gzip")
1025+
9731026

9741027
class TestExporterNames(TestCase):
9751028
@patch.dict(

0 commit comments

Comments
 (0)