From a09074460597aaa9031977209407858585e6609c Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 10 Dec 2025 12:01:15 -0800 Subject: [PATCH 1/6] Add filters for minimum severity level and trace based sampling --- .../src/opentelemetry/sdk/_logs/__init__.py | 2 + .../sdk/_logs/_internal/__init__.py | 56 ++++ opentelemetry-sdk/tests/logs/test_logs.py | 241 ++++++++++++++++++ 3 files changed, 299 insertions(+) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index ec0b3dfb23..ddc0f393ad 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -21,6 +21,7 @@ LogRecordDroppedAttributesWarning, LogRecordLimits, LogRecordProcessor, + FilteringLogRecordProcessor, ReadableLogRecord, ReadWriteLogRecord, ) @@ -32,6 +33,7 @@ "LogLimits", "LogRecordLimits", "LogRecordProcessor", + "FilteringLogRecordProcessor", "LogDroppedAttributesWarning", "LogRecordDroppedAttributesWarning", "ReadableLogRecord", diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index d775dd4455..ed3593bb89 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -55,6 +55,7 @@ from opentelemetry.trace import ( format_span_id, format_trace_id, + get_current_span, ) from opentelemetry.util.types import AnyValue, _ExtendedAttributes @@ -317,6 +318,35 @@ def force_flush(self, timeout_millis: int = 30000) -> bool: """ +class FilteringLogRecordProcessor(LogRecordProcessor): + """A processor that drops records based on minimum severity and/or trace based sampling parameters provided by the user.""" + + def __init__( + self, + log_record_processor: LogRecordProcessor, + *, + minimum_severity_level: SeverityNumber = SeverityNumber.UNSPECIFIED, + enable_trace_based_sampling: bool = False, + ): + self._log_record_processor = log_record_processor + self._minimum_severity_level = minimum_severity_level + self._enable_trace_based_sampling = enable_trace_based_sampling + + def on_emit(self, log_record: ReadWriteLogRecord): + record = log_record.log_record + if is_less_than_min_severity(record, self._minimum_severity_level): + return + if should_drop_logs_for_trace_based(record, self._enable_trace_based_sampling): + return + self._log_record_processor.on_emit(log_record) + + def shutdown(self): + self._log_record_processor.shutdown() + + def force_flush(self, timeout_millis: int = 30000) -> bool: + return self._log_record_processor.force_flush(timeout_millis) + + # Temporary fix until https://github.com/PyCQA/pylint/issues/4098 is resolved # pylint:disable=no-member class SynchronousMultiLogRecordProcessor(LogRecordProcessor): @@ -835,3 +865,29 @@ def std_to_otel(levelno: int) -> SeverityNumber: if levelno > 53: return SeverityNumber.FATAL4 return _STD_TO_OTEL[levelno] + + +def is_less_than_minimum_severity_level( + record: LogRecord, minimum_severity_level: SeverityNumber +) -> bool: + if record.severity_number is not None: + if ( + minimum_severity_level is not None + and minimum_severity_level != SeverityNumber.UNSPECIFIED + and record.severity_number.value < minimum_severity_level.value + ): + return True + return False + + +def should_drop_logs_for_trace_based_sampling( + record: LogRecord, enable_trace_based_sampling: bool +) -> bool: + if enable_trace_based_sampling: + if record.context is not None: + span = get_current_span(record.context) + span_context = span.get_span_context() + if span_context.is_valid and not span_context.trace_flags.sampled: + return True + return False + diff --git a/opentelemetry-sdk/tests/logs/test_logs.py b/opentelemetry-sdk/tests/logs/test_logs.py index 70811260ae..ae2ab51bd6 100644 --- a/opentelemetry-sdk/tests/logs/test_logs.py +++ b/opentelemetry-sdk/tests/logs/test_logs.py @@ -27,6 +27,7 @@ from opentelemetry.sdk._logs._internal import ( NoOpLogger, SynchronousMultiLogRecordProcessor, + FilteringLogRecordProcessor, ) from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED from opentelemetry.sdk.resources import Resource @@ -214,3 +215,243 @@ def test_can_emit_with_keywords_arguments(self): self.assertEqual(result_log_record.attributes, {"some": "attributes"}) self.assertEqual(result_log_record.event_name, "event_name") self.assertEqual(log_data.resource, logger.resource) + + def test_emit_logrecord_with_min_severity_filtering(self): + logger_processor_mock = Mock() + filtering_processor = FilteringLogRecordProcessor( + logger_processor_mock, + minimum_severity_level=SeverityNumber.DEBUG4, + ) + logger, _ = self._get_logger(filtering_processor) + + log_record_info = LogRecord( + observed_timestamp=0, + body="info log line", + severity_number=SeverityNumber.DEBUG, + severity_text="DEBUG", + ) + + logger.emit(log_record_info) + logger_processor_mock.on_emit.assert_not_called() + + logger_processor_mock.reset_mock() + + log_record_error = LogRecord( + observed_timestamp=0, + body="error log line", + severity_number=SeverityNumber.ERROR, + severity_text="ERROR", + ) + + logger.emit(log_record_error) + + logger_processor_mock.on_emit.assert_called_once() + log_data = logger_processor_mock.on_emit.call_args.args[0] + self.assertTrue(isinstance(log_data.log_record, LogRecord)) + self.assertEqual(log_data.log_record.severity_number, SeverityNumber.ERROR) + + def test_emit_logrecord_with_min_severity_unspecified(self): + logger_processor_mock = Mock() + filtering_processor = FilteringLogRecordProcessor( + logger_processor_mock, + minimum_severity_level=SeverityNumber.UNSPECIFIED, + ) + logger, _ = self._get_logger(filtering_processor) + log_record = LogRecord( + observed_timestamp=0, + body="debug log line", + severity_number=SeverityNumber.DEBUG, + severity_text="DEBUG", + ) + logger.emit(log_record) + logger_processor_mock.on_emit.assert_called_once() + + def test_emit_logrecord_with_trace_based_filtering(self): + logger_processor_mock = Mock() + filtering_processor = FilteringLogRecordProcessor( + logger_processor_mock, + enable_trace_based_sampling=True, + ) + logger, _ = self._get_logger(filtering_processor) + + mock_span_context = Mock() + mock_span_context.is_valid = True + mock_span_context.trace_flags.sampled = False + + mock_span = Mock() + mock_span.get_span_context.return_value = mock_span_context + + mock_context = Mock() + + with patch( + "opentelemetry.sdk._logs._internal.get_current_span", + return_value=mock_span, + ): + log_record = LogRecord( + observed_timestamp=0, + body="should be dropped", + severity_number=SeverityNumber.INFO, + severity_text="INFO", + context=mock_context, + ) + + logger.emit(log_record) + logger_processor_mock.on_emit.assert_not_called() + + logger_processor_mock.reset_mock() + + mock_span_context = Mock() + mock_span_context.is_valid = True + mock_span_context.trace_flags.sampled = True + + mock_span = Mock() + mock_span.get_span_context.return_value = mock_span_context + + with patch( + "opentelemetry.sdk._logs._internal.get_current_span", + return_value=mock_span, + ): + log_record = LogRecord( + observed_timestamp=0, + body="should pass", + severity_number=SeverityNumber.INFO, + severity_text="INFO", + context=mock_context, + ) + + logger.emit(log_record) + logger_processor_mock.on_emit.assert_called_once() + + def test_emit_logrecord_trace_filtering_disabled(self): + logger_processor_mock = Mock() + filtering_processor = FilteringLogRecordProcessor( + logger_processor_mock, + enable_trace_based_sampling=False, + ) + logger, _ = self._get_logger(filtering_processor) + + mock_span_context = Mock() + mock_span_context.is_valid = False + mock_span_context.trace_flags.sampled = False + + mock_span = Mock() + mock_span.get_span_context.return_value = mock_span_context + + mock_context = Mock() + + with patch( + "opentelemetry.sdk._logs._internal.get_current_span", + return_value=mock_span, + ): + log_record = LogRecord( + observed_timestamp=0, + body="should be emitted when filtering disabled", + severity_number=SeverityNumber.INFO, + severity_text="INFO", + context=mock_context, + ) + + logger.emit(log_record) + logger_processor_mock.on_emit.assert_called_once() + + def test_emit_logrecord_trace_filtering_edge_cases(self): + logger_processor_mock = Mock() + filtering_processor = FilteringLogRecordProcessor( + logger_processor_mock, + enable_trace_based_sampling=True, + ) + logger, _ = self._get_logger(filtering_processor) + + mock_span_context = Mock() + mock_span_context.is_valid = False + mock_span_context.trace_flags.sampled = True + + mock_span = Mock() + mock_span.get_span_context.return_value = mock_span_context + + mock_context = Mock() + + with patch( + "opentelemetry.sdk._logs._internal.get_current_span", + return_value=mock_span, + ): + log_record = LogRecord( + observed_timestamp=0, + body="invalid but sampled", + severity_number=SeverityNumber.INFO, + severity_text="INFO", + context=mock_context, + ) + + logger.emit(log_record) + logger_processor_mock.on_emit.assert_called_once() + + logger_processor_mock.reset_mock() + + mock_span_context = Mock() + mock_span_context.is_valid = True + mock_span_context.trace_flags.sampled = False + + mock_span = Mock() + mock_span.get_span_context.return_value = mock_span_context + + with patch( + "opentelemetry.sdk._logs._internal.get_current_span", + return_value=mock_span, + ): + log_record = LogRecord( + observed_timestamp=0, + body="valid but not sampled", + severity_number=SeverityNumber.INFO, + severity_text="INFO", + context=mock_context, + ) + + logger.emit(log_record) + logger_processor_mock.on_emit.assert_not_called() + + def test_emit_both_min_severity_and_trace_based_filtering(self): + logger_processor_mock = Mock() + filtering_processor = FilteringLogRecordProcessor( + logger_processor_mock, + minimum_severity_level=SeverityNumber.WARN, + enable_trace_based_sampling=True, + ) + logger, _ = self._get_logger(filtering_processor) + + mock_span_context = Mock() + mock_span_context.is_valid = True + mock_span_context.trace_flags.sampled = True + + mock_span = Mock() + mock_span.get_span_context.return_value = mock_span_context + + mock_context = Mock() + + with patch( + "opentelemetry.sdk._logs._internal.get_current_span", + return_value=mock_span, + ): + log_record_info = LogRecord( + observed_timestamp=0, + body="info log line", + severity_number=SeverityNumber.INFO, + severity_text="INFO", + context=mock_context, + ) + + logger.emit(log_record_info) + logger_processor_mock.on_emit.assert_not_called() + + logger_processor_mock.reset_mock() + + log_record_error = LogRecord( + observed_timestamp=0, + body="error log line", + severity_number=SeverityNumber.ERROR, + severity_text="ERROR", + context=mock_context, + ) + + logger.emit(log_record_error) + logger_processor_mock.on_emit.assert_called_once() From 709ab2291ed0e52c857c1a9064d504d57512f898 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 10 Dec 2025 12:07:13 -0800 Subject: [PATCH 2/6] Add CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3091794e0..1e96198049 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Add `minimum_severity_level` and `trace_based_sampling` logger parameters to filter logs + ([#4765](https://github.com/open-telemetry/opentelemetry-python/pull/4765)) - `opentelemetry-sdk`: Fix the type hint of the `_metrics_data` property to allow `None` ([#4837](https://github.com/open-telemetry/opentelemetry-python/pull/4837) - Regenerate opentelemetry-proto code with v1.9.0 release From 31e048026e1d1f84527f5852457a613565459f81 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 10 Dec 2025 15:46:23 -0800 Subject: [PATCH 3/6] Fix ruff and tests --- .../src/opentelemetry/sdk/_logs/__init__.py | 2 +- .../sdk/_logs/_internal/__init__.py | 21 +++- opentelemetry-sdk/tests/logs/test_logs.py | 107 +++++++++--------- 3 files changed, 76 insertions(+), 54 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index ddc0f393ad..777eae1467 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -13,6 +13,7 @@ # limitations under the License. from opentelemetry.sdk._logs._internal import ( + FilteringLogRecordProcessor, LogDroppedAttributesWarning, Logger, LoggerProvider, @@ -21,7 +22,6 @@ LogRecordDroppedAttributesWarning, LogRecordLimits, LogRecordProcessor, - FilteringLogRecordProcessor, ReadableLogRecord, ReadWriteLogRecord, ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index ed3593bb89..a3ab448a87 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -334,9 +334,13 @@ def __init__( def on_emit(self, log_record: ReadWriteLogRecord): record = log_record.log_record - if is_less_than_min_severity(record, self._minimum_severity_level): + if is_less_than_minimum_severity_level( + record, self._minimum_severity_level + ): return - if should_drop_logs_for_trace_based(record, self._enable_trace_based_sampling): + if should_drop_logs_for_trace_based_sampling( + record, self._enable_trace_based_sampling + ): return self._log_record_processor.on_emit(log_record) @@ -870,6 +874,12 @@ def std_to_otel(levelno: int) -> SeverityNumber: def is_less_than_minimum_severity_level( record: LogRecord, minimum_severity_level: SeverityNumber ) -> bool: + """Checks if the log record's severity number is less than the minimum severity level. + + :return: True if the log record's severity number is less than the minimum + severity level, False otherwise. Log records with an unspecified severity (i.e. `0`) + are not affected by this parameter and therefore bypass minimum severity filtering. + """ if record.severity_number is not None: if ( minimum_severity_level is not None @@ -883,6 +893,13 @@ def is_less_than_minimum_severity_level( def should_drop_logs_for_trace_based_sampling( record: LogRecord, enable_trace_based_sampling: bool ) -> bool: + """Determines whether the logger should drop log records associated with unsampled traces. + + If `enable_trace_based_sampling` is `true`, log records associated with unsampled traces are dropped by the `Logger`. + A log record is considered associated with an unsampled trace if it has a valid `SpanId` and its + `TraceFlags` indicate that the trace is unsampled. A log record that isn't associated with a trace + context is not affected by this parameter and therefore bypasses trace-based filtering. + """ if enable_trace_based_sampling: if record.context is not None: span = get_current_span(record.context) diff --git a/opentelemetry-sdk/tests/logs/test_logs.py b/opentelemetry-sdk/tests/logs/test_logs.py index ae2ab51bd6..56491873db 100644 --- a/opentelemetry-sdk/tests/logs/test_logs.py +++ b/opentelemetry-sdk/tests/logs/test_logs.py @@ -25,9 +25,9 @@ ReadableLogRecord, ) from opentelemetry.sdk._logs._internal import ( + FilteringLogRecordProcessor, NoOpLogger, SynchronousMultiLogRecordProcessor, - FilteringLogRecordProcessor, ) from opentelemetry.sdk.environment_variables import OTEL_SDK_DISABLED from opentelemetry.sdk.resources import Resource @@ -216,13 +216,33 @@ def test_can_emit_with_keywords_arguments(self): self.assertEqual(result_log_record.event_name, "event_name") self.assertEqual(log_data.resource, logger.resource) - def test_emit_logrecord_with_min_severity_filtering(self): - logger_processor_mock = Mock() + +class TestFilteringLogRecordProcessor(unittest.TestCase): + @staticmethod + def _build_logger( + minimum_severity_level: SeverityNumber = SeverityNumber.UNSPECIFIED, + enable_trace_based_sampling: bool = False, + ): + processor_mock = Mock() filtering_processor = FilteringLogRecordProcessor( - logger_processor_mock, - minimum_severity_level=SeverityNumber.DEBUG4, + processor_mock, + minimum_severity_level=minimum_severity_level, + enable_trace_based_sampling=enable_trace_based_sampling, + ) + provider = LoggerProvider(resource=Resource.create({})) + provider.add_log_record_processor(filtering_processor) + logger = provider.get_logger( + "name", + version="version", + schema_url="schema_url", + attributes={"an": "attribute"}, + ) + return logger, processor_mock + + def test_emit_logrecord_with_minimum_severity_level_filtering(self): + logger, processor_mock = self._build_logger( + minimum_severity_level=SeverityNumber.DEBUG4 ) - logger, _ = self._get_logger(filtering_processor) log_record_info = LogRecord( observed_timestamp=0, @@ -232,9 +252,9 @@ def test_emit_logrecord_with_min_severity_filtering(self): ) logger.emit(log_record_info) - logger_processor_mock.on_emit.assert_not_called() + processor_mock.on_emit.assert_not_called() - logger_processor_mock.reset_mock() + processor_mock.reset_mock() log_record_error = LogRecord( observed_timestamp=0, @@ -245,18 +265,15 @@ def test_emit_logrecord_with_min_severity_filtering(self): logger.emit(log_record_error) - logger_processor_mock.on_emit.assert_called_once() - log_data = logger_processor_mock.on_emit.call_args.args[0] + processor_mock.on_emit.assert_called_once() + log_data = processor_mock.on_emit.call_args.args[0] self.assertTrue(isinstance(log_data.log_record, LogRecord)) - self.assertEqual(log_data.log_record.severity_number, SeverityNumber.ERROR) - - def test_emit_logrecord_with_min_severity_unspecified(self): - logger_processor_mock = Mock() - filtering_processor = FilteringLogRecordProcessor( - logger_processor_mock, - minimum_severity_level=SeverityNumber.UNSPECIFIED, + self.assertEqual( + log_data.log_record.severity_number, SeverityNumber.ERROR ) - logger, _ = self._get_logger(filtering_processor) + + def test_emit_logrecord_with_minimum_severity_level_unspecified(self): + logger, processor_mock = self._build_logger() log_record = LogRecord( observed_timestamp=0, body="debug log line", @@ -264,15 +281,12 @@ def test_emit_logrecord_with_min_severity_unspecified(self): severity_text="DEBUG", ) logger.emit(log_record) - logger_processor_mock.on_emit.assert_called_once() + processor_mock.on_emit.assert_called_once() def test_emit_logrecord_with_trace_based_filtering(self): - logger_processor_mock = Mock() - filtering_processor = FilteringLogRecordProcessor( - logger_processor_mock, - enable_trace_based_sampling=True, + logger, processor_mock = self._build_logger( + enable_trace_based_sampling=True ) - logger, _ = self._get_logger(filtering_processor) mock_span_context = Mock() mock_span_context.is_valid = True @@ -296,9 +310,9 @@ def test_emit_logrecord_with_trace_based_filtering(self): ) logger.emit(log_record) - logger_processor_mock.on_emit.assert_not_called() + processor_mock.on_emit.assert_not_called() - logger_processor_mock.reset_mock() + processor_mock.reset_mock() mock_span_context = Mock() mock_span_context.is_valid = True @@ -320,15 +334,12 @@ def test_emit_logrecord_with_trace_based_filtering(self): ) logger.emit(log_record) - logger_processor_mock.on_emit.assert_called_once() + processor_mock.on_emit.assert_called_once() - def test_emit_logrecord_trace_filtering_disabled(self): - logger_processor_mock = Mock() - filtering_processor = FilteringLogRecordProcessor( - logger_processor_mock, - enable_trace_based_sampling=False, + def test_emit_logrecord_trace_based_filtering_disabled(self): + logger, processor_mock = self._build_logger( + enable_trace_based_sampling=False ) - logger, _ = self._get_logger(filtering_processor) mock_span_context = Mock() mock_span_context.is_valid = False @@ -352,15 +363,12 @@ def test_emit_logrecord_trace_filtering_disabled(self): ) logger.emit(log_record) - logger_processor_mock.on_emit.assert_called_once() + processor_mock.on_emit.assert_called_once() - def test_emit_logrecord_trace_filtering_edge_cases(self): - logger_processor_mock = Mock() - filtering_processor = FilteringLogRecordProcessor( - logger_processor_mock, - enable_trace_based_sampling=True, + def test_emit_logrecord_trace_based_filtering_edge_cases(self): + logger, processor_mock = self._build_logger( + enable_trace_based_sampling=True ) - logger, _ = self._get_logger(filtering_processor) mock_span_context = Mock() mock_span_context.is_valid = False @@ -384,9 +392,9 @@ def test_emit_logrecord_trace_filtering_edge_cases(self): ) logger.emit(log_record) - logger_processor_mock.on_emit.assert_called_once() + processor_mock.on_emit.assert_called_once() - logger_processor_mock.reset_mock() + processor_mock.reset_mock() mock_span_context = Mock() mock_span_context.is_valid = True @@ -408,16 +416,13 @@ def test_emit_logrecord_trace_filtering_edge_cases(self): ) logger.emit(log_record) - logger_processor_mock.on_emit.assert_not_called() + processor_mock.on_emit.assert_not_called() - def test_emit_both_min_severity_and_trace_based_filtering(self): - logger_processor_mock = Mock() - filtering_processor = FilteringLogRecordProcessor( - logger_processor_mock, + def test_emit_both_minimum_severity_level_and_trace_based_filtering(self): + logger, processor_mock = self._build_logger( minimum_severity_level=SeverityNumber.WARN, enable_trace_based_sampling=True, ) - logger, _ = self._get_logger(filtering_processor) mock_span_context = Mock() mock_span_context.is_valid = True @@ -441,9 +446,9 @@ def test_emit_both_min_severity_and_trace_based_filtering(self): ) logger.emit(log_record_info) - logger_processor_mock.on_emit.assert_not_called() + processor_mock.on_emit.assert_not_called() - logger_processor_mock.reset_mock() + processor_mock.reset_mock() log_record_error = LogRecord( observed_timestamp=0, @@ -454,4 +459,4 @@ def test_emit_both_min_severity_and_trace_based_filtering(self): ) logger.emit(log_record_error) - logger_processor_mock.on_emit.assert_called_once() + processor_mock.on_emit.assert_called_once() From d8f18b06b21118c80a00bdb4ccad869de6e297aa Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 10 Dec 2025 15:57:43 -0800 Subject: [PATCH 4/6] Remove extra line --- .../src/opentelemetry/sdk/_logs/_internal/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index a3ab448a87..1b98e5d771 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -907,4 +907,3 @@ def should_drop_logs_for_trace_based_sampling( if span_context.is_valid and not span_context.trace_flags.sampled: return True return False - From 6ee26972dfa165c73ce2299520309593dcfab729 Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 10 Dec 2025 16:27:06 -0800 Subject: [PATCH 5/6] Remove extra line --- .../src/opentelemetry/sdk/_logs/_internal/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 1b98e5d771..bc6fa2141f 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -906,4 +906,4 @@ def should_drop_logs_for_trace_based_sampling( span_context = span.get_span_context() if span_context.is_valid and not span_context.trace_flags.sampled: return True - return False + return False \ No newline at end of file From 13acc99605ec3e95b4a85a0446229d7d50b703ea Mon Sep 17 00:00:00 2001 From: Radhika Gupta Date: Wed, 10 Dec 2025 16:48:41 -0800 Subject: [PATCH 6/6] Add back terminating line --- .../src/opentelemetry/sdk/_logs/_internal/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index bc6fa2141f..1b98e5d771 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -906,4 +906,4 @@ def should_drop_logs_for_trace_based_sampling( span_context = span.get_span_context() if span_context.is_valid and not span_context.trace_flags.sampled: return True - return False \ No newline at end of file + return False