Skip to content
Open
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
1 change: 1 addition & 0 deletions .changelog/5724.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`opentelemetry-sdk`: make `Logger.enabled()` respect the configured minimum severity and trace-based filtering
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
from opentelemetry.trace import (
format_span_id,
format_trace_id,
get_current_span,
)
from opentelemetry.util.types import AnyValue, Attributes

Expand Down Expand Up @@ -731,6 +732,8 @@ def flush(self) -> None:
@dataclass
class _LoggerConfig:
is_enabled: bool = True
minimum_severity: SeverityNumber = SeverityNumber.UNSPECIFIED
trace_based: bool = False

@classmethod
def default(cls) -> _LoggerConfig:
Expand Down Expand Up @@ -770,6 +773,16 @@ def enabled(
) -> bool:
if not self._logger_config.is_enabled:
return False
if (
severity_number is not None
and severity_number is not SeverityNumber.UNSPECIFIED
and severity_number.value < self._logger_config.minimum_severity.value
):
return False
if self._logger_config.trace_based:
span_context = get_current_span(context).get_span_context()
if span_context.is_valid and not span_context.trace_flags.sampled:
return False
return self._multi_log_record_processor.enabled(
context=context,
instrumentation_scope=self._instrumentation_scope,
Expand Down
70 changes: 70 additions & 0 deletions opentelemetry-sdk/tests/logs/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
_scope_name_matches_glob,
)
from opentelemetry.semconv.attributes import exception_attributes
from opentelemetry.trace import (
NonRecordingSpan,
SpanContext,
TraceFlags,
set_span_in_context,
)


class TestLoggerProvider(unittest.TestCase):
Expand Down Expand Up @@ -503,6 +509,70 @@ def test_enabled_disabled_logger_returns_false(self):
logger = provider.get_logger("test")
self.assertFalse(logger.enabled())

def test_enabled_below_minimum_severity_returns_false(self):
logger, processor = self._get_logger()
logger._set_logger_config(_LoggerConfig(minimum_severity=SeverityNumber.WARN))

self.assertFalse(logger.enabled(severity_number=SeverityNumber.INFO4))
processor.enabled.assert_not_called()

def test_enabled_at_or_above_minimum_severity_returns_true(self):
logger, processor = self._get_logger()
logger._set_logger_config(_LoggerConfig(minimum_severity=SeverityNumber.WARN))
processor.enabled.return_value = True

self.assertTrue(logger.enabled(severity_number=SeverityNumber.WARN))
self.assertTrue(logger.enabled(severity_number=SeverityNumber.ERROR))

def test_enabled_unspecified_severity_bypasses_minimum_severity(self):
logger, processor = self._get_logger()
logger._set_logger_config(_LoggerConfig(minimum_severity=SeverityNumber.WARN))
processor.enabled.return_value = True

self.assertTrue(logger.enabled())
self.assertTrue(logger.enabled(severity_number=SeverityNumber.UNSPECIFIED))

def test_enabled_trace_based_unsampled_trace_returns_false(self):
logger, processor = self._get_logger()
logger._set_logger_config(_LoggerConfig(trace_based=True))
context = set_span_in_context(
NonRecordingSpan(
SpanContext(
trace_id=1,
span_id=1,
is_remote=False,
trace_flags=TraceFlags.get_default(),
)
)
)

self.assertFalse(logger.enabled(context=context))
processor.enabled.assert_not_called()

def test_enabled_trace_based_sampled_trace_returns_true(self):
logger, processor = self._get_logger()
logger._set_logger_config(_LoggerConfig(trace_based=True))
processor.enabled.return_value = True
context = set_span_in_context(
NonRecordingSpan(
SpanContext(
trace_id=1,
span_id=1,
is_remote=False,
trace_flags=TraceFlags(TraceFlags.SAMPLED),
)
)
)

self.assertTrue(logger.enabled(context=context))

def test_enabled_trace_based_without_trace_returns_true(self):
logger, processor = self._get_logger()
logger._set_logger_config(_LoggerConfig(trace_based=True))
processor.enabled.return_value = True

self.assertTrue(logger.enabled(context=get_current()))

def test_enabled_passes_args_to_processor(self): # pylint: disable=no-self-use
provider = LoggerProvider()
processor_mock = Mock()
Expand Down