Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1e68c3c
Initial Commit
DylanRussell Jul 16, 2025
06dee51
Fix broken tests
DylanRussell Jul 17, 2025
c500b15
Start writing test
DylanRussell Jul 17, 2025
a6dcd1c
Fix tests
DylanRussell Jul 17, 2025
5ef26f2
Merge branch 'main' of github.com:DylanRussell/opentelemetry-python i…
DylanRussell Jul 18, 2025
2e76e59
Add changelog
DylanRussell Jul 18, 2025
9344ebd
Improne and fix _init_exporter func
DylanRussell Jul 18, 2025
cc89293
Fix desc
DylanRussell Jul 18, 2025
f27856f
Run precommit and update variable
DylanRussell Jul 21, 2025
82d72bb
Update changelog
DylanRussell Jul 21, 2025
2244d5a
Merge branch 'main' into add_cred_envvar
DylanRussell Jul 21, 2025
afaf88d
Merge remote-tracking branch 'origin' into add_cred_envvar
DylanRussell Aug 12, 2025
4881780
Fix_type
DylanRussell Aug 12, 2025
66fb14d
Commit changes
DylanRussell Aug 12, 2025
fcadee2
Add test
DylanRussell Aug 13, 2025
6c2740a
fix envvar and typecheck
DylanRussell Aug 13, 2025
0dc2861
Precommit and constraints
DylanRussell Aug 13, 2025
99a55d4
Move change to exporter
DylanRussell Aug 25, 2025
9bf07a7
Move common code to util.
DylanRussell Aug 25, 2025
ae576c1
Merge branch 'main' into add_cred_envvar
DylanRussell Aug 25, 2025
65f177b
Fix lint err and print statment
DylanRussell Sep 2, 2025
ffeb2d2
Merge branch 'main' into add_cred_envvar
DylanRussell Sep 2, 2025
efe5a94
Update opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/…
DylanRussell Sep 8, 2025
0b21293
Respond to comments
DylanRussell Sep 8, 2025
205efa3
Merge branch 'add_cred_envvar' of github.com:DylanRussell/opentelemet…
DylanRussell Sep 8, 2025
810ec49
Ruff
DylanRussell Sep 8, 2025
9b95dfa
Document the entry points better
DylanRussell Sep 8, 2025
9934efe
Going with factory function approach w/ 2 entry points
DylanRussell Sep 8, 2025
24119fb
Add tests.. Fix tox.ini ?
DylanRussell Sep 8, 2025
813c11c
Add http/grpc env var variants
DylanRussell Sep 8, 2025
97fa836
Respond to comments
DylanRussell Sep 8, 2025
e7027a0
Rename python env var with _
DylanRussell Sep 8, 2025
f06d8db
Precommit
DylanRussell Sep 8, 2025
3ab6126
Commit changes
DylanRussell Sep 8, 2025
3e409cc
add new line
DylanRussell Sep 8, 2025
5632fe0
Fix docs error..
DylanRussell Sep 8, 2025
f0fc0f6
get rid of envvar in docstring
DylanRussell Sep 8, 2025
0e0fb9d
Revert tox.ini changes
DylanRussell Sep 9, 2025
5336c95
Revert tox
DylanRussell Sep 9, 2025
0fcdd7b
Merge branch 'main' into add_cred_envvar
DylanRussell Sep 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Overwrite logging.config.fileConfig and logging.config.dictConfig to ensure
the OTLP `LogHandler` remains attached to the root logger. Fix a bug that
can cause a deadlock to occur over `logging._lock` in some cases ([#4636](https://github.com/open-telemetry/opentelemetry-python/pull/4636)).
- Add new environment variables to the SDK `OTEL_PYTHON_EXPORTER_OTLP_{METRICS/TRACES/LOGS}_CREDENTIAL_PROVIDER` that can be used to
inject a `requests.Session` or `grpc.ChannelCredentials` object into OTLP exporters created during auto instrumentation.

## Version 1.35.0/0.56b0 (2025-07-11)

Expand Down
124 changes: 118 additions & 6 deletions opentelemetry-sdk/src/opentelemetry/sdk/_configuration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@

from __future__ import annotations

import inspect
import logging
import logging.config
import os
from abc import ABC, abstractmethod
from os import environ
from typing import Any, Callable, Mapping, Sequence, Type, Union
from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union

from grpc import ChannelCredentials # pylint: disable=import-error
from requests import Session
from typing_extensions import Literal

from opentelemetry._events import set_event_logger_provider
Expand All @@ -46,6 +49,10 @@
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL,
OTEL_EXPORTER_OTLP_PROTOCOL,
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL,
OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER,
OTEL_PYTHON_EXPORTER_OTLP_LOGS_CREDENTIAL_PROVIDER,
OTEL_PYTHON_EXPORTER_OTLP_METRICS_CREDENTIAL_PROVIDER,
OTEL_PYTHON_EXPORTER_OTLP_TRACES_CREDENTIAL_PROVIDER,
OTEL_TRACES_SAMPLER,
OTEL_TRACES_SAMPLER_ARG,
)
Expand Down Expand Up @@ -79,6 +86,12 @@
"logs": OTEL_LOGS_EXPORTER,
}

_EXPORTER_CREDENTIAL_BY_SIGNAL_TYPE = {
"traces": OTEL_PYTHON_EXPORTER_OTLP_TRACES_CREDENTIAL_PROVIDER,
"metrics": OTEL_PYTHON_EXPORTER_OTLP_METRICS_CREDENTIAL_PROVIDER,
"logs": OTEL_PYTHON_EXPORTER_OTLP_LOGS_CREDENTIAL_PROVIDER,
}

_PROTOCOL_ENV_BY_SIGNAL_TYPE = {
"traces": OTEL_EXPORTER_OTLP_TRACES_PROTOCOL,
"metrics": OTEL_EXPORTER_OTLP_METRICS_PROTOCOL,
Expand All @@ -103,6 +116,36 @@
]


def _load_credential_from_envvar(
environment_variable: str,
) -> Optional[
tuple[
Literal["credentials", "session"], Union[ChannelCredentials, Session]
]
]:
credential_env = os.getenv(environment_variable)
if credential_env:
credentials = _import_config_component(
credential_env, "opentelemetry_otlp_credential_provider"
)()
if isinstance(credentials, ChannelCredentials):
return ("credentials", credentials)
elif isinstance(credentials, Session):
return ("session", credentials)
else:
raise RuntimeError(
f"{credential_env} is neither a grpc.ChannelCredentials or requests.Session type."
)


def _import_config_component(
selected_component: str, entry_point_name: str
) -> Type:
return _import_config_components([selected_component], entry_point_name)[
0
][1]


def _import_config_components(
selected_components: Sequence[str], entry_point_name: str
) -> list[tuple[str, Type]]:
Expand Down Expand Up @@ -202,12 +245,48 @@ def _get_exporter_names(
]


def _init_exporter(
signal_type: Literal["traces", "metrics", "logs"],
exporter_args: ExporterArgsMap,
exporter_class: Union[
Type[SpanExporter], Type[MetricExporter], Type[LogExporter]
],
otlp_credential_param_for_all_signal_types: Optional[
tuple[
Literal["credentials", "session"],
Union[ChannelCredentials, Session],
]
] = None,
) -> Union[SpanExporter, MetricExporter, LogExporter]:
# Per signal type envvar should take precedence over all signal type env var.
otlp_credential_param = (
_load_credential_from_envvar(
_EXPORTER_CREDENTIAL_BY_SIGNAL_TYPE[signal_type]
)
or otlp_credential_param_for_all_signal_types
)
if otlp_credential_param:
credential_key, credential = otlp_credential_param
# We only want to inject credentials into the appropriate OTLP HTTP // GRPC exporters.
if credential_key in inspect.signature(
exporter_class.__init__
).parameters and (
"opentelemetry.exporter.otlp.proto.http" in str(exporter_class)
or "opentelemetry.exporter.otlp.proto.grpc" in str(exporter_class)
):
exporter_args[credential_key] = credential
return exporter_class(**exporter_args)


def _init_tracing(
exporters: dict[str, Type[SpanExporter]],
id_generator: IdGenerator | None = None,
sampler: Sampler | None = None,
resource: Resource | None = None,
exporter_args_map: ExporterArgsMap | None = None,
otlp_credential_param: Optional[
tuple[str, Union[ChannelCredentials, Session]]
] = None,
):
provider = TracerProvider(
id_generator=id_generator,
Expand All @@ -220,16 +299,26 @@ def _init_tracing(
for _, exporter_class in exporters.items():
exporter_args = exporter_args_map.get(exporter_class, {})
provider.add_span_processor(
BatchSpanProcessor(exporter_class(**exporter_args))
BatchSpanProcessor(
_init_exporter(
"traces",
exporter_args,
exporter_class,
otlp_credential_param,
)
)
)


def _init_metrics(
exporters_or_readers: dict[
str, Union[Type[MetricExporter], Type[MetricReader]]
],
resource: Resource | None = None,
resource: Resource = None,
exporter_args_map: ExporterArgsMap | None = None,
otlp_credential_param: Optional[
tuple[str, Union[ChannelCredentials, Session]]
] = None,
):
metric_readers = []

Expand All @@ -241,7 +330,12 @@ def _init_metrics(
else:
metric_readers.append(
PeriodicExportingMetricReader(
exporter_or_reader_class(**exporter_args)
_init_exporter(
"metrics",
exporter_args,
exporter_or_reader_class,
otlp_credential_param,
)
)
)

Expand All @@ -254,6 +348,9 @@ def _init_logging(
resource: Resource | None = None,
setup_logging_handler: bool = True,
exporter_args_map: ExporterArgsMap | None = None,
otlp_credential_param: Optional[
tuple[str, Union[ChannelCredentials, Session]]
] = None,
):
provider = LoggerProvider(resource=resource)
set_logger_provider(provider)
Expand All @@ -262,7 +359,14 @@ def _init_logging(
for _, exporter_class in exporters.items():
exporter_args = exporter_args_map.get(exporter_class, {})
provider.add_log_record_processor(
BatchLogRecordProcessor(exporter_class(**exporter_args))
BatchLogRecordProcessor(
_init_exporter(
"logs",
exporter_args,
exporter_class,
otlp_credential_param,
)
)
)

event_logger_provider = EventLoggerProvider(logger_provider=provider)
Expand Down Expand Up @@ -445,15 +549,22 @@ def _initialize_components(
# from the env variable else defaults to "unknown_service"
resource = Resource.create(resource_attributes)

otlp_credential_param = _load_credential_from_envvar(
OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER
)
_init_tracing(
exporters=span_exporters,
id_generator=id_generator,
sampler=sampler,
resource=resource,
otlp_credential_param=otlp_credential_param,
exporter_args_map=exporter_args_map,
)
_init_metrics(
metric_exporters, resource, exporter_args_map=exporter_args_map
metric_exporters,
resource,
otlp_credential_param=otlp_credential_param,
exporter_args_map=exporter_args_map,
)
if setup_logging_handler is None:
setup_logging_handler = (
Expand All @@ -468,6 +579,7 @@ def _initialize_components(
log_exporters,
resource,
setup_logging_handler,
otlp_credential_param=otlp_credential_param,
exporter_args_map=exporter_args_map,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,43 @@
A scheme of https indicates a secure connection and takes precedence over this configuration setting.
"""

OTEL_PYTHON_EXPORTER_OTLP_LOGS_CREDENTIAL_PROVIDER = (
"OTEL_PYTHON_EXPORTER_OTLP_LOGS_CREDENTIAL_PROVIDER"
)
"""
.. envvar:: OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER

The :envvar:`OTEL_PYTHON_EXPORTER_OTLP_LOGS_CREDENTIAL_PROVIDER` provides either ChannelCredentials for grpc OTLP Log exporters,
or request.Session for HTTP Log exporters.
"""
OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER = (
"OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER"
)
"""
.. envvar:: OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER

The :envvar:`OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER` provides either ChannelCredentials for all grpc OTLP exporters,
or request.Session for HTTP exporters.
"""
OTEL_PYTHON_EXPORTER_OTLP_TRACES_CREDENTIAL_PROVIDER = (
"OTEL_PYTHON_EXPORTER_OTLP_TRACES_CREDENTIAL_PROVIDER"
)
"""
.. envvar:: OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER

The :envvar:`OTEL_PYTHON_EXPORTER_OTLP_TRACES_CREDENTIAL_PROVIDER` provides either ChannelCredentials for grpc OTLP Span exporters,
or request.Session for HTTP Span exporters.
"""
OTEL_PYTHON_EXPORTER_OTLP_METRICS_CREDENTIAL_PROVIDER = (
"OTEL_PYTHON_EXPORTER_OTLP_METRICS_CREDENTIAL_PROVIDER"
)
"""
.. envvar:: OTEL_PYTHON_EXPORTER_OTLP_CREDENTIAL_PROVIDER

The :envvar:`OTEL_PYTHON_EXPORTER_OTLP_METRICS_CREDENTIAL_PROVIDER` provides either ChannelCredentials for grpc OTLP Metric exporters,
or request.Session for HTTP Metric exporters.
"""

OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE = "OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE"
"""
.. envvar:: OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE
Expand Down
2 changes: 2 additions & 0 deletions opentelemetry-sdk/test-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ py-cpuinfo==9.0.0
pytest==7.4.4
tomli==2.0.1
typing_extensions==4.10.0
grpcio==1.66.2
requests==2.32.3
wrapt==1.16.0
zipp==3.19.2
-e tests/opentelemetry-test-utils
Expand Down
Loading
Loading