Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 6 additions & 2 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#
build==1.4.4
# via pip-tools
certifi==2026.4.22
certifi==2026.5.20
# via requests
charset-normalizer==3.4.7
# via requests
Expand Down Expand Up @@ -38,6 +38,7 @@ opentelemetry-api==1.41.1
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
# opentelemetry-instrumentation
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-system-metrics
# opentelemetry-opamp-client
# opentelemetry-resourcedetector-gcp
Expand All @@ -57,7 +58,10 @@ opentelemetry-exporter-otlp-proto-http==1.41.1
opentelemetry-instrumentation==0.62b1
# via
# elastic-opentelemetry (pyproject.toml)
# opentelemetry-instrumentation-logging
# opentelemetry-instrumentation-system-metrics
opentelemetry-instrumentation-logging==0.62b1
# via elastic-opentelemetry (pyproject.toml)
opentelemetry-instrumentation-system-metrics==0.62b1
# via elastic-opentelemetry (pyproject.toml)
opentelemetry-opamp-client==0.2b0
Expand Down Expand Up @@ -146,7 +150,7 @@ uuid-utils==0.15.0
# opentelemetry-opamp-client
wheel==0.47.0
# via pip-tools
wrapt==2.1.2
wrapt==2.2.0
# via opentelemetry-instrumentation
zipp==3.23.1
# via importlib-metadata
Expand Down
9 changes: 8 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ dependencies = [
]

[project.optional-dependencies]
dev = ["pytest", "pip-tools", "oteltest==0.24.0", "leb128", "pytest-vcr ; python_version > '3.9'"]
dev = [
"pytest",
"pip-tools",
"oteltest==0.24.0",
"leb128",
"pytest-vcr ; python_version > '3.9'",
"opentelemetry-instrumentation-logging",
]

[project.entry-points.opentelemetry_configurator]
configurator = "elasticotel.distro:ElasticOpenTelemetryConfigurator"
Expand Down
22 changes: 20 additions & 2 deletions src/elasticotel/distro/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@
OpAMPRemoteConfigParseException,
)
from opentelemetry._opamp.proto import opamp_pb2 as opamp_pb2
from opentelemetry.sdk._logs import LoggingHandler

try:
from opentelemetry.instrumentation.logging.handler import LoggingHandler # type: ignore[reportAssignmentType]
except ImportError:

class LoggingHandler:
pass


from opentelemetry.sdk._logs import LoggingHandler as SDKLoggingHandler
from opentelemetry.sdk.environment_variables import OTEL_LOG_LEVEL, OTEL_TRACES_SAMPLER_ARG
from opentelemetry.sdk.trace import _TracerConfig
from opentelemetry.sdk.util._configurator import ConfiguratorRulesT
Expand Down Expand Up @@ -129,7 +138,16 @@ def _setup_logging(self):
_logger.addHandler(handler)
# We need to propagate if we have the OTel handler otherwise we don't see logs shipped, in the other
# cases we shouldn't
_logger.propagate = any(isinstance(_handler, LoggingHandler) for _handler in logging.root.handlers)
_logger.propagate = any(
isinstance(
_handler,
(
LoggingHandler,
SDKLoggingHandler,
),
)
for _handler in logging.root.handlers
)

# do validation, we only validate logging_level because sampling_rate is handled by the sdk already
logging_level = _LOG_LEVELS_MAP.get(self.logging_level.value)
Expand Down
30 changes: 28 additions & 2 deletions tests/distro/test_distro.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import json
import logging
import os
from unittest import TestCase, mock
from unittest import TestCase, mock, skipIf

from elasticotel.distro import ElasticOpenTelemetryConfigurator, ElasticOpenTelemetryDistro, logger as distro_logger
from elasticotel.distro.config import EDOTOpAMPCallbacks, logger as config_logger, Config
Expand All @@ -40,7 +40,12 @@
OTEL_METRICS_EXPORTER,
OTEL_TRACES_EXPORTER,
)
from opentelemetry.sdk._logs import LoggingHandler

try:
from opentelemetry.instrumentation.logging.handler import LoggingHandler
except ImportError:
LoggingHandler = None
from opentelemetry.sdk._logs import LoggingHandler as SDKLoggingHandler
from opentelemetry.sdk.environment_variables import (
OTEL_EXPERIMENTAL_RESOURCE_DETECTORS,
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE,
Expand Down Expand Up @@ -459,6 +464,27 @@ def test_logging_setup_add_handlers_only_once(self):
_logger.removeHandler(_logger.handlers[0])

def test_logging_setup_set_propagate_true_if_sdk_logging_handler_found(self):
root_logger = logging.getLogger()
handler = SDKLoggingHandler(logger_provider=mock.Mock())
root_logger.addHandler(handler)

config = Config()

config._setup_logging()

for _logger in config._get_loggers():
with self.subTest(logger=_logger):
self.assertEqual(len(_logger.handlers), 1)
self.assertTrue(_logger.propagate)

# cleanup
_logger.removeHandler(_logger.handlers[0])
_logger.propagate = True

root_logger.removeHandler(handler)

@skipIf(LoggingHandler is None, "opentelemetry-instrumentation-logging not installed")
def test_logging_setup_set_propagate_true_if_logging_instrumentation_handler_found(self):
root_logger = logging.getLogger()
handler = LoggingHandler(logger_provider=mock.Mock())
root_logger.addHandler(handler)
Expand Down
Loading