From 41386dff50d7c9188352e2582fe49c97d66ec177 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Mon, 13 Oct 2025 18:15:21 +0200 Subject: [PATCH 01/13] WIP warnings before deprecations and renames --- .../sdk/_logs/_internal/__init__.py | 16 ++++++++++++++++ .../sdk/_logs/_internal/export/__init__.py | 14 +++++++++++++- .../_internal/export/in_memory_log_exporter.py | 9 ++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 6a029b8759d..debb18556dd 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -147,6 +147,12 @@ def __init__( OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, ) + warnings.warn( + "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", + LogDeprecatedInitWarning, + stacklevel=0, + ) + def __repr__(self): return f"{type(self).__name__}(max_attributes={self.max_attributes}, max_attribute_length={self.max_attribute_length})" @@ -234,6 +240,11 @@ def __init__( # pylint:disable=too-many-locals limits: LogLimits | None = None, event_name: str | None = None, ): + warnings.warn( + "LogRecord will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", + LogDeprecatedInitWarning, + stacklevel=0, + ) if not context: context = get_current() @@ -358,6 +369,11 @@ def __init__( log_record: LogRecord, instrumentation_scope: InstrumentationScope, ): + warnings.warn( + "LogData will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", + LogDeprecatedInitWarning, + stacklevel=0, + ) self.log_record = log_record self.instrumentation_scope = instrumentation_scope diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index 411f92aec18..2b60d729808 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -17,6 +17,7 @@ import enum import logging import sys +import warnings from os import environ, linesep from typing import IO, Callable, Optional, Sequence @@ -26,7 +27,12 @@ detach, set_value, ) -from opentelemetry.sdk._logs import LogData, LogRecord, LogRecordProcessor +from opentelemetry.sdk._logs import ( + LogData, + LogDeprecatedInitWarning, + LogRecord, + LogRecordProcessor, +) from opentelemetry.sdk._shared_internal import BatchProcessor, DuplicateFilter from opentelemetry.sdk.environment_variables import ( OTEL_BLRP_EXPORT_TIMEOUT, @@ -93,6 +99,12 @@ def __init__( self.out = out self.formatter = formatter + warnings.warn( + "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", + LogDeprecatedInitWarning, + stacklevel=0, + ) + def export(self, batch: Sequence[LogData]): for data in batch: self.out.write(self.formatter(data.log_record)) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py index 68cb6b7389a..0a94f66e535 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py @@ -14,8 +14,9 @@ import threading import typing +import warnings -from opentelemetry.sdk._logs import LogData +from opentelemetry.sdk._logs import LogData, LogDeprecatedInitWarning from opentelemetry.sdk._logs.export import LogExporter, LogExportResult @@ -32,6 +33,12 @@ def __init__(self): self._lock = threading.Lock() self._stopped = False + warnings.warn( + "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", + LogDeprecatedInitWarning, + stacklevel=0, + ) + def clear(self) -> None: with self._lock: self._logs.clear() From 0c2a4a047688e9bb7a089f7d6e6cf5608cda661e Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Mon, 13 Oct 2025 15:55:32 -0400 Subject: [PATCH 02/13] different classes --- .../src/opentelemetry/sdk/_logs/__init__.py | 14 +++- .../sdk/_logs/_internal/__init__.py | 72 +++++++++++++++++-- .../sdk/_logs/_internal/export/__init__.py | 4 +- .../export/in_memory_log_exporter.py | 4 +- 4 files changed, 82 insertions(+), 12 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index dbb108b7dba..3d27277ab81 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -15,7 +15,12 @@ from opentelemetry.sdk._logs._internal import ( LogData, - LogDeprecatedInitWarning, + LogLimitsInitDeprecatedWarning, + LogRecordInitDeprecatedWarning, + LogDataInitDeprecatedWarning, + LogRecordContextDeprecatedWarning, + InMemoryLogExporterDeprecatedWarning, + ConsoleLogExporterDeprecatedWarning, LogDroppedAttributesWarning, Logger, LoggerProvider, @@ -33,6 +38,11 @@ "LogLimits", "LogRecord", "LogRecordProcessor", - "LogDeprecatedInitWarning", + "LogLimitsInitDeprecatedWarning", + "LogRecordInitDeprecatedWarning", "LogDroppedAttributesWarning", + "LogDataInitDeprecatedWarning", + "LogRecordContextDeprecatedWarning", + "InMemoryLogExporterDeprecatedWarning", + "ConsoleLogExporterDeprecatedWarning", ] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index debb18556dd..c4a2772f884 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -84,7 +84,19 @@ class LogDroppedAttributesWarning(UserWarning): warnings.simplefilter("once", LogDroppedAttributesWarning) -class LogDeprecatedInitWarning(UserWarning): +class LogLimitsInitDeprecatedWarning(UserWarning): + """Custom warning to indicate deprecated LogLimits init was used. + + This class is used to filter and handle these specific warnings separately + from other warnings, ensuring that they are only shown once without + interfering with default user warnings. + """ + + +warnings.simplefilter("once", LogLimitsInitDeprecatedWarning) + + +class LogRecordInitDeprecatedWarning(UserWarning): """Custom warning to indicate deprecated LogRecord init was used. This class is used to filter and handle these specific warnings separately @@ -93,7 +105,55 @@ class LogDeprecatedInitWarning(UserWarning): """ -warnings.simplefilter("once", LogDeprecatedInitWarning) +warnings.simplefilter("once", LogRecordInitDeprecatedWarning) + + +class LogDataInitDeprecatedWarning(UserWarning): + """Custom warning to indicate deprecated LogData init was used. + + This class is used to filter and handle these specific warnings separately + from other warnings, ensuring that they are only shown once without + interfering with default user warnings. + """ + + +warnings.simplefilter("once", LogDataInitDeprecatedWarning) + + +class LogRecordContextDeprecatedWarning(UserWarning): + """Custom warning to indicate LogRecord was initialized without using context. + + This class is used to filter and handle these specific warnings separately + from other warnings, ensuring that they are only shown once without + interfering with default user warnings. + """ + + +warnings.simplefilter("once", LogRecordContextDeprecatedWarning) + + +class InMemoryLogExporterDeprecatedWarning(UserWarning): + """Custom warning to indicate InMemoryLogExporter is deprecated. + + This class is used to filter and handle these specific warnings separately + from other warnings, ensuring that they are only shown once without + interfering with default user warnings. + """ + + +warnings.simplefilter("once", LogRecordContextDeprecatedWarning) + + +class ConsoleLogExporterDeprecatedWarning(UserWarning): + """Custom warning to indicate ConsoleLogExporter is deprecated. + + This class is used to filter and handle these specific warnings separately + from other warnings, ensuring that they are only shown once without + interfering with default user warnings. + """ + + +warnings.simplefilter("once", ConsoleLogExporterDeprecatedWarning) class LogLimits: @@ -149,7 +209,7 @@ def __init__( warnings.warn( "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", - LogDeprecatedInitWarning, + LogLimitsInitDeprecatedWarning, stacklevel=0, ) @@ -242,7 +302,7 @@ def __init__( # pylint:disable=too-many-locals ): warnings.warn( "LogRecord will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", - LogDeprecatedInitWarning, + LogRecordInitDeprecatedWarning, stacklevel=0, ) if not context: @@ -251,7 +311,7 @@ def __init__( # pylint:disable=too-many-locals if trace_id or span_id or trace_flags: warnings.warn( "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead.", - LogDeprecatedInitWarning, + LogRecordContextDeprecatedWarning, stacklevel=2, ) @@ -371,7 +431,7 @@ def __init__( ): warnings.warn( "LogData will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", - LogDeprecatedInitWarning, + LogDataInitDeprecatedWarning, stacklevel=0, ) self.log_record = log_record diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index 2b60d729808..ad8dbaa6c12 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -29,7 +29,7 @@ ) from opentelemetry.sdk._logs import ( LogData, - LogDeprecatedInitWarning, + ConsoleLogExporterDeprecatedWarning, LogRecord, LogRecordProcessor, ) @@ -101,7 +101,7 @@ def __init__( warnings.warn( "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", - LogDeprecatedInitWarning, + ConsoleLogExporterDeprecatedWarning, stacklevel=0, ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py index 0a94f66e535..b900d1d57db 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py @@ -16,7 +16,7 @@ import typing import warnings -from opentelemetry.sdk._logs import LogData, LogDeprecatedInitWarning +from opentelemetry.sdk._logs import LogData, InMemoryLogExporterDeprecatedWarning from opentelemetry.sdk._logs.export import LogExporter, LogExportResult @@ -35,7 +35,7 @@ def __init__(self): warnings.warn( "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", - LogDeprecatedInitWarning, + InMemoryLogExporterDeprecatedWarning, stacklevel=0, ) From 4c2c04fcef4e1d25cf54a9081ac68548157446df Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Mon, 13 Oct 2025 16:32:08 -0400 Subject: [PATCH 03/13] tests --- CHANGELOG.md | 2 + opentelemetry-sdk/tests/logs/test_export.py | 87 +++++++++++++++++++ .../tests/logs/test_log_limits.py | 43 ++++++++- .../tests/logs/test_log_record.py | 60 +++++++++++-- 4 files changed, 182 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90fcb56cb7e..9acd47712b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#4755](https://github.com/open-telemetry/opentelemetry-python/pull/4755)) - logs: extend Logger.emit to accept separated keyword arguments ([#4737](https://github.com/open-telemetry/opentelemetry-python/pull/4737)) +- logs: Added different warning classes as necessary for log class deprecation + ([#4771](https://github.com/open-telemetry/opentelemetry-python/pull/4771)) ## Version 1.37.0/0.58b0 (2025-09-11) diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 4b8d98693c5..cafa6b5d63e 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -17,6 +17,7 @@ import os import time import unittest +import warnings from concurrent.futures import ThreadPoolExecutor from sys import version_info from unittest.mock import Mock, patch @@ -26,6 +27,8 @@ from opentelemetry._logs import SeverityNumber from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( + ConsoleLogExporterDeprecatedWarning, + InMemoryLogExporterDeprecatedWarning, LogData, LoggerProvider, LoggingHandler, @@ -647,3 +650,87 @@ def formatter(record): # pylint: disable=unused-argument exporter.export([EMPTY_LOG]) mock_stdout.write.assert_called_once_with(mock_record_str) + + def test_console_log_exporter_deprecated_warning(self): + """Test that ConsoleLogExporter initialization emits a deprecation warning.""" + with warnings.catch_warnings(record=True) as cw: + warnings.simplefilter("always") + ConsoleLogExporter() + + # Check that at least one ConsoleLogExporterDeprecatedWarning was emitted + console_warnings = [ + w for w in cw if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) + ] + self.assertGreater(len(console_warnings), 0, + "Expected at least one ConsoleLogExporterDeprecatedWarning") + + # Check the message content of the ConsoleLogExporterDeprecatedWarning + warning_message = str(console_warnings[0].message) + self.assertIn( + "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", + warning_message, + ) + + def test_console_log_exporter_deprecated_warning_once(self): + """Test that ConsoleLogExporter deprecation warning is only shown once due to simplefilter('once').""" + with warnings.catch_warnings(record=True) as cw: + # Multiple instantiations should only warn once due to simplefilter("once") + for _ in range(10): + ConsoleLogExporter() + + # Check that exactly one ConsoleLogExporterDeprecatedWarning was emitted + console_warnings = [ + w for w in cw if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) + ] + self.assertEqual(len(console_warnings), 1, + "Expected exactly one ConsoleLogExporterDeprecatedWarning due to simplefilter('once')") + + # Check the message content + warning_message = str(console_warnings[0].message) + self.assertIn( + "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", + warning_message, + ) + + +class TestInMemoryLogExporterDeprecation(unittest.TestCase): + def test_in_memory_log_exporter_deprecated_warning(self): + """Test that InMemoryLogExporter initialization emits a deprecation warning.""" + with warnings.catch_warnings(record=True) as cw: + warnings.simplefilter("always") + InMemoryLogExporter() + + # Check that at least one InMemoryLogExporterDeprecatedWarning was emitted + in_memory_warnings = [ + w for w in cw if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) + ] + self.assertGreater(len(in_memory_warnings), 0, + "Expected at least one InMemoryLogExporterDeprecatedWarning") + + # Check the message content of the InMemoryLogExporterDeprecatedWarning + warning_message = str(in_memory_warnings[0].message) + self.assertIn( + "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", + warning_message, + ) + + def test_in_memory_log_exporter_deprecated_warning_once(self): + """Test that InMemoryLogExporter deprecation warning is only shown once due to simplefilter('once').""" + with warnings.catch_warnings(record=True) as cw: + # Multiple instantiations should only warn once due to simplefilter("once") + for _ in range(10): + InMemoryLogExporter() + + # Check that exactly one InMemoryLogExporterDeprecatedWarning was emitted + in_memory_warnings = [ + w for w in cw if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) + ] + self.assertEqual(len(in_memory_warnings), 1, + "Expected exactly one InMemoryLogExporterDeprecatedWarning due to simplefilter('once')") + + # Check the message content + warning_message = str(in_memory_warnings[0].message) + self.assertIn( + "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", + warning_message, + ) diff --git a/opentelemetry-sdk/tests/logs/test_log_limits.py b/opentelemetry-sdk/tests/logs/test_log_limits.py index 82a7ce9b4d6..1262d08ca7f 100644 --- a/opentelemetry-sdk/tests/logs/test_log_limits.py +++ b/opentelemetry-sdk/tests/logs/test_log_limits.py @@ -13,9 +13,10 @@ # limitations under the License. import unittest +import warnings from unittest.mock import patch -from opentelemetry.sdk._logs import LogLimits +from opentelemetry.sdk._logs import LogLimits, LogLimitsInitDeprecatedWarning from opentelemetry.sdk._logs._internal import ( _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT, ) @@ -70,3 +71,43 @@ def test_invalid_env_vars_raise(self): str(error.exception), f"Unexpected error message for {env_var}={bad_value}", ) + + def test_log_limits_init_deprecated_warning(self): + """Test that LogLimits initialization emits a deprecation warning.""" + with warnings.catch_warnings(record=True) as cw: + warnings.simplefilter("always") + LogLimits() + + self.assertEqual(len(cw), 1) + self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) + self.assertIn( + "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", + str(cw[-1].message), + ) + + def test_log_limits_init_deprecated_warning_with_params(self): + """Test that LogLimits initialization with parameters still emits a deprecation warning.""" + with warnings.catch_warnings(record=True) as cw: + warnings.simplefilter("always") + LogLimits(max_attributes=10, max_attribute_length=100) + + self.assertEqual(len(cw), 1) + self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) + self.assertIn( + "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", + str(cw[-1].message), + ) + + def test_log_limits_init_deprecated_warning_once(self): + """Test that LogLimits deprecation warning is only shown once due to simplefilter('once').""" + with warnings.catch_warnings(record=True) as cw: + # Multiple instantiations should only warn once due to simplefilter("once") + for _ in range(10): + LogLimits() + + self.assertEqual(len(cw), 1) + self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) + self.assertIn( + "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", + str(cw[-1].message), + ) diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index d5f2745d248..aba210c9eac 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -21,7 +21,8 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.context import get_current from opentelemetry.sdk._logs import ( - LogDeprecatedInitWarning, + LogRecordContextDeprecatedWarning, + LogRecordInitDeprecatedWarning, LogDroppedAttributesWarning, LogLimits, LogRecord, @@ -142,11 +143,19 @@ def test_log_record_dropped_attributes_set_limits_warning_once(self): attributes=attr, limits=limits, ) - self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogDroppedAttributesWarning) + + # Check that at least one LogDroppedAttributesWarning was emitted + dropped_attributes_warnings = [ + w for w in cw if isinstance(w.message, LogDroppedAttributesWarning) + ] + self.assertEqual(len(dropped_attributes_warnings), 1, + "Expected exactly one LogDroppedAttributesWarning due to simplefilter('once')") + + # Check the message content of the LogDroppedAttributesWarning + warning_message = str(dropped_attributes_warnings[0].message) self.assertIn( "Log record attributes were dropped due to limits", - str(cw[-1].message), + warning_message, ) def test_log_record_dropped_attributes_unset_limits(self): @@ -159,7 +168,7 @@ def test_log_record_dropped_attributes_unset_limits(self): self.assertTrue(result.dropped_attributes == 0) self.assertEqual(attr, result.attributes) - def test_log_record_deprecated_init_warning(self): + def test_log_record_context_deprecated_init_warning(self): test_cases = [ {"trace_id": 123}, {"span_id": 123}, @@ -172,17 +181,50 @@ def test_log_record_deprecated_init_warning(self): for _ in range(10): LogRecord(**params) - self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) + # Check that at least one LogRecordContextDeprecatedWarning was emitted + context_deprecated_warnings = [ + w for w in cw if isinstance(w.message, LogRecordContextDeprecatedWarning) + ] + self.assertEqual(len(context_deprecated_warnings), 1, + "Expected exactly one LogRecordContextDeprecatedWarning due to simplefilter('once')") + + # Check the message content of the LogRecordContextDeprecatedWarning + warning_message = str(context_deprecated_warnings[0].message) self.assertIn( "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead.", - str(cw[-1].message), + warning_message, ) with warnings.catch_warnings(record=True) as cw: for _ in range(10): LogRecord(context=get_current()) - self.assertEqual(len(cw), 0) + + # Check that no LogRecordContextDeprecatedWarning was emitted when using context + context_deprecated_warnings = [ + w for w in cw if isinstance(w.message, LogRecordContextDeprecatedWarning) + ] + self.assertEqual(len(context_deprecated_warnings), 0, + "Expected no LogRecordContextDeprecatedWarning when using context parameter") + + def test_log_record_init_deprecated_warning(self): + """Test that LogRecord initialization emits a LogRecordInitDeprecatedWarning.""" + with warnings.catch_warnings(record=True) as cw: + warnings.simplefilter("always") + LogRecord() + + # Check that at least one LogRecordInitDeprecatedWarning was emitted + log_record_init_warnings = [ + w for w in cw if isinstance(w.message, LogRecordInitDeprecatedWarning) + ] + self.assertGreater(len(log_record_init_warnings), 0, + "Expected at least one LogRecordInitDeprecatedWarning") + + # Check the message content of the LogRecordInitDeprecatedWarning + warning_message = str(log_record_init_warnings[0].message) + self.assertIn( + "LogRecord will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", + warning_message, + ) # pylint:disable=protected-access def test_log_record_from_api_log_record(self): From 00958837d787709b253b07413831a2997ed3b782 Mon Sep 17 00:00:00 2001 From: Leighton Chen Date: Mon, 13 Oct 2025 16:42:13 -0400 Subject: [PATCH 04/13] lint --- opentelemetry-sdk/tests/logs/test_export.py | 60 ++++++++++++------- .../tests/logs/test_log_limits.py | 6 +- .../tests/logs/test_log_record.py | 56 +++++++++++------ 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index cafa6b5d63e..4d04d59189e 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -656,14 +656,19 @@ def test_console_log_exporter_deprecated_warning(self): with warnings.catch_warnings(record=True) as cw: warnings.simplefilter("always") ConsoleLogExporter() - + # Check that at least one ConsoleLogExporterDeprecatedWarning was emitted console_warnings = [ - w for w in cw if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) + w + for w in cw + if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) ] - self.assertGreater(len(console_warnings), 0, - "Expected at least one ConsoleLogExporterDeprecatedWarning") - + self.assertGreater( + len(console_warnings), + 0, + "Expected at least one ConsoleLogExporterDeprecatedWarning", + ) + # Check the message content of the ConsoleLogExporterDeprecatedWarning warning_message = str(console_warnings[0].message) self.assertIn( @@ -677,14 +682,19 @@ def test_console_log_exporter_deprecated_warning_once(self): # Multiple instantiations should only warn once due to simplefilter("once") for _ in range(10): ConsoleLogExporter() - + # Check that exactly one ConsoleLogExporterDeprecatedWarning was emitted console_warnings = [ - w for w in cw if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) + w + for w in cw + if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) ] - self.assertEqual(len(console_warnings), 1, - "Expected exactly one ConsoleLogExporterDeprecatedWarning due to simplefilter('once')") - + self.assertEqual( + len(console_warnings), + 1, + "Expected exactly one ConsoleLogExporterDeprecatedWarning due to simplefilter('once')", + ) + # Check the message content warning_message = str(console_warnings[0].message) self.assertIn( @@ -699,14 +709,19 @@ def test_in_memory_log_exporter_deprecated_warning(self): with warnings.catch_warnings(record=True) as cw: warnings.simplefilter("always") InMemoryLogExporter() - + # Check that at least one InMemoryLogExporterDeprecatedWarning was emitted in_memory_warnings = [ - w for w in cw if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) + w + for w in cw + if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) ] - self.assertGreater(len(in_memory_warnings), 0, - "Expected at least one InMemoryLogExporterDeprecatedWarning") - + self.assertGreater( + len(in_memory_warnings), + 0, + "Expected at least one InMemoryLogExporterDeprecatedWarning", + ) + # Check the message content of the InMemoryLogExporterDeprecatedWarning warning_message = str(in_memory_warnings[0].message) self.assertIn( @@ -720,14 +735,19 @@ def test_in_memory_log_exporter_deprecated_warning_once(self): # Multiple instantiations should only warn once due to simplefilter("once") for _ in range(10): InMemoryLogExporter() - + # Check that exactly one InMemoryLogExporterDeprecatedWarning was emitted in_memory_warnings = [ - w for w in cw if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) + w + for w in cw + if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) ] - self.assertEqual(len(in_memory_warnings), 1, - "Expected exactly one InMemoryLogExporterDeprecatedWarning due to simplefilter('once')") - + self.assertEqual( + len(in_memory_warnings), + 1, + "Expected exactly one InMemoryLogExporterDeprecatedWarning due to simplefilter('once')", + ) + # Check the message content warning_message = str(in_memory_warnings[0].message) self.assertIn( diff --git a/opentelemetry-sdk/tests/logs/test_log_limits.py b/opentelemetry-sdk/tests/logs/test_log_limits.py index 1262d08ca7f..7b6113da3e8 100644 --- a/opentelemetry-sdk/tests/logs/test_log_limits.py +++ b/opentelemetry-sdk/tests/logs/test_log_limits.py @@ -77,7 +77,7 @@ def test_log_limits_init_deprecated_warning(self): with warnings.catch_warnings(record=True) as cw: warnings.simplefilter("always") LogLimits() - + self.assertEqual(len(cw), 1) self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) self.assertIn( @@ -90,7 +90,7 @@ def test_log_limits_init_deprecated_warning_with_params(self): with warnings.catch_warnings(record=True) as cw: warnings.simplefilter("always") LogLimits(max_attributes=10, max_attribute_length=100) - + self.assertEqual(len(cw), 1) self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) self.assertIn( @@ -104,7 +104,7 @@ def test_log_limits_init_deprecated_warning_once(self): # Multiple instantiations should only warn once due to simplefilter("once") for _ in range(10): LogLimits() - + self.assertEqual(len(cw), 1) self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) self.assertIn( diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index aba210c9eac..6a311fcaaa1 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -21,11 +21,11 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.context import get_current from opentelemetry.sdk._logs import ( - LogRecordContextDeprecatedWarning, - LogRecordInitDeprecatedWarning, LogDroppedAttributesWarning, LogLimits, LogRecord, + LogRecordContextDeprecatedWarning, + LogRecordInitDeprecatedWarning, ) from opentelemetry.sdk.resources import Resource from opentelemetry.trace.span import TraceFlags @@ -143,14 +143,17 @@ def test_log_record_dropped_attributes_set_limits_warning_once(self): attributes=attr, limits=limits, ) - + # Check that at least one LogDroppedAttributesWarning was emitted dropped_attributes_warnings = [ w for w in cw if isinstance(w.message, LogDroppedAttributesWarning) ] - self.assertEqual(len(dropped_attributes_warnings), 1, - "Expected exactly one LogDroppedAttributesWarning due to simplefilter('once')") - + self.assertEqual( + len(dropped_attributes_warnings), + 1, + "Expected exactly one LogDroppedAttributesWarning due to simplefilter('once')", + ) + # Check the message content of the LogDroppedAttributesWarning warning_message = str(dropped_attributes_warnings[0].message) self.assertIn( @@ -183,11 +186,16 @@ def test_log_record_context_deprecated_init_warning(self): # Check that at least one LogRecordContextDeprecatedWarning was emitted context_deprecated_warnings = [ - w for w in cw if isinstance(w.message, LogRecordContextDeprecatedWarning) + w + for w in cw + if isinstance(w.message, LogRecordContextDeprecatedWarning) ] - self.assertEqual(len(context_deprecated_warnings), 1, - "Expected exactly one LogRecordContextDeprecatedWarning due to simplefilter('once')") - + self.assertEqual( + len(context_deprecated_warnings), + 1, + "Expected exactly one LogRecordContextDeprecatedWarning due to simplefilter('once')", + ) + # Check the message content of the LogRecordContextDeprecatedWarning warning_message = str(context_deprecated_warnings[0].message) self.assertIn( @@ -198,27 +206,37 @@ def test_log_record_context_deprecated_init_warning(self): with warnings.catch_warnings(record=True) as cw: for _ in range(10): LogRecord(context=get_current()) - + # Check that no LogRecordContextDeprecatedWarning was emitted when using context context_deprecated_warnings = [ - w for w in cw if isinstance(w.message, LogRecordContextDeprecatedWarning) + w + for w in cw + if isinstance(w.message, LogRecordContextDeprecatedWarning) ] - self.assertEqual(len(context_deprecated_warnings), 0, - "Expected no LogRecordContextDeprecatedWarning when using context parameter") + self.assertEqual( + len(context_deprecated_warnings), + 0, + "Expected no LogRecordContextDeprecatedWarning when using context parameter", + ) def test_log_record_init_deprecated_warning(self): """Test that LogRecord initialization emits a LogRecordInitDeprecatedWarning.""" with warnings.catch_warnings(record=True) as cw: warnings.simplefilter("always") LogRecord() - + # Check that at least one LogRecordInitDeprecatedWarning was emitted log_record_init_warnings = [ - w for w in cw if isinstance(w.message, LogRecordInitDeprecatedWarning) + w + for w in cw + if isinstance(w.message, LogRecordInitDeprecatedWarning) ] - self.assertGreater(len(log_record_init_warnings), 0, - "Expected at least one LogRecordInitDeprecatedWarning") - + self.assertGreater( + len(log_record_init_warnings), + 0, + "Expected at least one LogRecordInitDeprecatedWarning", + ) + # Check the message content of the LogRecordInitDeprecatedWarning warning_message = str(log_record_init_warnings[0].message) self.assertIn( From fbce7a516d039ea17e953612ebd5031dc004ead3 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 14 Oct 2025 10:29:40 +0200 Subject: [PATCH 05/13] Keep using one warning --- .../src/opentelemetry/sdk/_logs/__init__.py | 14 +--- .../sdk/_logs/_internal/__init__.py | 74 ++----------------- .../sdk/_logs/_internal/export/__init__.py | 4 +- .../export/in_memory_log_exporter.py | 4 +- opentelemetry-sdk/tests/logs/test_export.py | 39 ++++------ .../tests/logs/test_log_limits.py | 8 +- .../tests/logs/test_log_record.py | 54 +++++++------- 7 files changed, 59 insertions(+), 138 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py index 3d27277ab81..dbb108b7dba 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/__init__.py @@ -15,12 +15,7 @@ from opentelemetry.sdk._logs._internal import ( LogData, - LogLimitsInitDeprecatedWarning, - LogRecordInitDeprecatedWarning, - LogDataInitDeprecatedWarning, - LogRecordContextDeprecatedWarning, - InMemoryLogExporterDeprecatedWarning, - ConsoleLogExporterDeprecatedWarning, + LogDeprecatedInitWarning, LogDroppedAttributesWarning, Logger, LoggerProvider, @@ -38,11 +33,6 @@ "LogLimits", "LogRecord", "LogRecordProcessor", - "LogLimitsInitDeprecatedWarning", - "LogRecordInitDeprecatedWarning", + "LogDeprecatedInitWarning", "LogDroppedAttributesWarning", - "LogDataInitDeprecatedWarning", - "LogRecordContextDeprecatedWarning", - "InMemoryLogExporterDeprecatedWarning", - "ConsoleLogExporterDeprecatedWarning", ] diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index c4a2772f884..f96d02870b6 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -84,8 +84,8 @@ class LogDroppedAttributesWarning(UserWarning): warnings.simplefilter("once", LogDroppedAttributesWarning) -class LogLimitsInitDeprecatedWarning(UserWarning): - """Custom warning to indicate deprecated LogLimits init was used. +class LogDeprecatedInitWarning(UserWarning): + """Custom warning to indicate that deprecated and soon to be deprecated Log classes was used. This class is used to filter and handle these specific warnings separately from other warnings, ensuring that they are only shown once without @@ -93,67 +93,7 @@ class LogLimitsInitDeprecatedWarning(UserWarning): """ -warnings.simplefilter("once", LogLimitsInitDeprecatedWarning) - - -class LogRecordInitDeprecatedWarning(UserWarning): - """Custom warning to indicate deprecated LogRecord init was used. - - This class is used to filter and handle these specific warnings separately - from other warnings, ensuring that they are only shown once without - interfering with default user warnings. - """ - - -warnings.simplefilter("once", LogRecordInitDeprecatedWarning) - - -class LogDataInitDeprecatedWarning(UserWarning): - """Custom warning to indicate deprecated LogData init was used. - - This class is used to filter and handle these specific warnings separately - from other warnings, ensuring that they are only shown once without - interfering with default user warnings. - """ - - -warnings.simplefilter("once", LogDataInitDeprecatedWarning) - - -class LogRecordContextDeprecatedWarning(UserWarning): - """Custom warning to indicate LogRecord was initialized without using context. - - This class is used to filter and handle these specific warnings separately - from other warnings, ensuring that they are only shown once without - interfering with default user warnings. - """ - - -warnings.simplefilter("once", LogRecordContextDeprecatedWarning) - - -class InMemoryLogExporterDeprecatedWarning(UserWarning): - """Custom warning to indicate InMemoryLogExporter is deprecated. - - This class is used to filter and handle these specific warnings separately - from other warnings, ensuring that they are only shown once without - interfering with default user warnings. - """ - - -warnings.simplefilter("once", LogRecordContextDeprecatedWarning) - - -class ConsoleLogExporterDeprecatedWarning(UserWarning): - """Custom warning to indicate ConsoleLogExporter is deprecated. - - This class is used to filter and handle these specific warnings separately - from other warnings, ensuring that they are only shown once without - interfering with default user warnings. - """ - - -warnings.simplefilter("once", ConsoleLogExporterDeprecatedWarning) +warnings.simplefilter("once", LogDeprecatedInitWarning) class LogLimits: @@ -209,7 +149,7 @@ def __init__( warnings.warn( "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", - LogLimitsInitDeprecatedWarning, + LogDeprecatedInitWarning, stacklevel=0, ) @@ -302,7 +242,7 @@ def __init__( # pylint:disable=too-many-locals ): warnings.warn( "LogRecord will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", - LogRecordInitDeprecatedWarning, + LogDeprecatedInitWarning, stacklevel=0, ) if not context: @@ -311,7 +251,7 @@ def __init__( # pylint:disable=too-many-locals if trace_id or span_id or trace_flags: warnings.warn( "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead.", - LogRecordContextDeprecatedWarning, + LogDeprecatedInitWarning, stacklevel=2, ) @@ -431,7 +371,7 @@ def __init__( ): warnings.warn( "LogData will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", - LogDataInitDeprecatedWarning, + LogDeprecatedInitWarning, stacklevel=0, ) self.log_record = log_record diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index ad8dbaa6c12..2b60d729808 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -29,7 +29,7 @@ ) from opentelemetry.sdk._logs import ( LogData, - ConsoleLogExporterDeprecatedWarning, + LogDeprecatedInitWarning, LogRecord, LogRecordProcessor, ) @@ -101,7 +101,7 @@ def __init__( warnings.warn( "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", - ConsoleLogExporterDeprecatedWarning, + LogDeprecatedInitWarning, stacklevel=0, ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py index b900d1d57db..0a94f66e535 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py @@ -16,7 +16,7 @@ import typing import warnings -from opentelemetry.sdk._logs import LogData, InMemoryLogExporterDeprecatedWarning +from opentelemetry.sdk._logs import LogData, LogDeprecatedInitWarning from opentelemetry.sdk._logs.export import LogExporter, LogExportResult @@ -35,7 +35,7 @@ def __init__(self): warnings.warn( "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", - InMemoryLogExporterDeprecatedWarning, + LogDeprecatedInitWarning, stacklevel=0, ) diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 4d04d59189e..2d822d18386 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -27,9 +27,8 @@ from opentelemetry._logs import SeverityNumber from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( - ConsoleLogExporterDeprecatedWarning, - InMemoryLogExporterDeprecatedWarning, LogData, + LogDeprecatedInitWarning, LoggerProvider, LoggingHandler, LogRecord, @@ -657,19 +656,17 @@ def test_console_log_exporter_deprecated_warning(self): warnings.simplefilter("always") ConsoleLogExporter() - # Check that at least one ConsoleLogExporterDeprecatedWarning was emitted + # Check that at least one LogDeprecatedInitWarning, was emitted console_warnings = [ - w - for w in cw - if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] self.assertGreater( len(console_warnings), 0, - "Expected at least one ConsoleLogExporterDeprecatedWarning", + "Expected at least one LogDeprecatedInitWarning", ) - # Check the message content of the ConsoleLogExporterDeprecatedWarning + # Check the message content of the warning warning_message = str(console_warnings[0].message) self.assertIn( "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", @@ -683,16 +680,14 @@ def test_console_log_exporter_deprecated_warning_once(self): for _ in range(10): ConsoleLogExporter() - # Check that exactly one ConsoleLogExporterDeprecatedWarning was emitted + # Check that exactly one LogDeprecatedInitWarning was emitted console_warnings = [ - w - for w in cw - if isinstance(w.message, ConsoleLogExporterDeprecatedWarning) + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] self.assertEqual( len(console_warnings), 1, - "Expected exactly one ConsoleLogExporterDeprecatedWarning due to simplefilter('once')", + "Expected exactly one LogDeprecatedInitWarning due to simplefilter('once')", ) # Check the message content @@ -710,19 +705,17 @@ def test_in_memory_log_exporter_deprecated_warning(self): warnings.simplefilter("always") InMemoryLogExporter() - # Check that at least one InMemoryLogExporterDeprecatedWarning was emitted + # Check that at least one LogDeprecatedInitWarning was emitted in_memory_warnings = [ - w - for w in cw - if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] self.assertGreater( len(in_memory_warnings), 0, - "Expected at least one InMemoryLogExporterDeprecatedWarning", + "Expected at least one LogDeprecatedInitWarning", ) - # Check the message content of the InMemoryLogExporterDeprecatedWarning + # Check the message content of the warning warning_message = str(in_memory_warnings[0].message) self.assertIn( "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", @@ -736,16 +729,14 @@ def test_in_memory_log_exporter_deprecated_warning_once(self): for _ in range(10): InMemoryLogExporter() - # Check that exactly one InMemoryLogExporterDeprecatedWarning was emitted + # Check that exactly one LogDeprecatedInitWarning was emitted in_memory_warnings = [ - w - for w in cw - if isinstance(w.message, InMemoryLogExporterDeprecatedWarning) + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] self.assertEqual( len(in_memory_warnings), 1, - "Expected exactly one InMemoryLogExporterDeprecatedWarning due to simplefilter('once')", + "Expected exactly one LogDeprecatedInitWarning due to simplefilter('once')", ) # Check the message content diff --git a/opentelemetry-sdk/tests/logs/test_log_limits.py b/opentelemetry-sdk/tests/logs/test_log_limits.py index 7b6113da3e8..5fda9f0b666 100644 --- a/opentelemetry-sdk/tests/logs/test_log_limits.py +++ b/opentelemetry-sdk/tests/logs/test_log_limits.py @@ -16,7 +16,7 @@ import warnings from unittest.mock import patch -from opentelemetry.sdk._logs import LogLimits, LogLimitsInitDeprecatedWarning +from opentelemetry.sdk._logs import LogDeprecatedInitWarning, LogLimits from opentelemetry.sdk._logs._internal import ( _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT, ) @@ -79,7 +79,7 @@ def test_log_limits_init_deprecated_warning(self): LogLimits() self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) + self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) self.assertIn( "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", str(cw[-1].message), @@ -92,7 +92,7 @@ def test_log_limits_init_deprecated_warning_with_params(self): LogLimits(max_attributes=10, max_attribute_length=100) self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) + self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) self.assertIn( "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", str(cw[-1].message), @@ -106,7 +106,7 @@ def test_log_limits_init_deprecated_warning_once(self): LogLimits() self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogLimitsInitDeprecatedWarning) + self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) self.assertIn( "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", str(cw[-1].message), diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index 6a311fcaaa1..651c4801cfd 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -21,11 +21,10 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.context import get_current from opentelemetry.sdk._logs import ( + LogDeprecatedInitWarning, LogDroppedAttributesWarning, LogLimits, LogRecord, - LogRecordContextDeprecatedWarning, - LogRecordInitDeprecatedWarning, ) from opentelemetry.sdk.resources import Resource from opentelemetry.trace.span import TraceFlags @@ -184,40 +183,43 @@ def test_log_record_context_deprecated_init_warning(self): for _ in range(10): LogRecord(**params) - # Check that at least one LogRecordContextDeprecatedWarning was emitted + # Check that the LogDeprecatedInitWarning was emitted context_deprecated_warnings = [ w for w in cw - if isinstance(w.message, LogRecordContextDeprecatedWarning) + if isinstance(w.message, LogDeprecatedInitWarning) ] - self.assertEqual( - len(context_deprecated_warnings), - 1, - "Expected exactly one LogRecordContextDeprecatedWarning due to simplefilter('once')", - ) + self.assertEqual(len(context_deprecated_warnings), 3) - # Check the message content of the LogRecordContextDeprecatedWarning - warning_message = str(context_deprecated_warnings[0].message) - self.assertIn( - "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead.", - warning_message, - ) + # Check we have the expected message once + log_record_context_warning = [ + w.message + for w in cw + if "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead." + in str(w.message) + ] + + self.assertEqual(len(log_record_context_warning), 1) with warnings.catch_warnings(record=True) as cw: for _ in range(10): LogRecord(context=get_current()) - # Check that no LogRecordContextDeprecatedWarning was emitted when using context + # Check that no LogDeprecatedInitWarning was emitted when using context context_deprecated_warnings = [ - w + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) + ] + self.assertEqual(len(context_deprecated_warnings), 2) + + # Check we have no message + log_record_context_warning = [ + w.message for w in cw - if isinstance(w.message, LogRecordContextDeprecatedWarning) + if "LogRecord init with `trace_id`, `span_id`, and/or `trace_flags` is deprecated since 1.35.0. Use `context` instead." + in str(w.message) ] - self.assertEqual( - len(context_deprecated_warnings), - 0, - "Expected no LogRecordContextDeprecatedWarning when using context parameter", - ) + + self.assertEqual(len(log_record_context_warning), 0) def test_log_record_init_deprecated_warning(self): """Test that LogRecord initialization emits a LogRecordInitDeprecatedWarning.""" @@ -225,11 +227,9 @@ def test_log_record_init_deprecated_warning(self): warnings.simplefilter("always") LogRecord() - # Check that at least one LogRecordInitDeprecatedWarning was emitted + # Check that at least one LogDeprecatedInitWarning was emitted log_record_init_warnings = [ - w - for w in cw - if isinstance(w.message, LogRecordInitDeprecatedWarning) + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] self.assertGreater( len(log_record_init_warnings), From bc8887bd611047591f1f927930920dc7ffef8f68 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 14 Oct 2025 10:30:45 +0200 Subject: [PATCH 06/13] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9acd47712b7..9538426481f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#4755](https://github.com/open-telemetry/opentelemetry-python/pull/4755)) - logs: extend Logger.emit to accept separated keyword arguments ([#4737](https://github.com/open-telemetry/opentelemetry-python/pull/4737)) -- logs: Added different warning classes as necessary for log class deprecation +- logs: add warnings for classes that would be deprecated and renamed in 1.39.0 ([#4771](https://github.com/open-telemetry/opentelemetry-python/pull/4771)) ## Version 1.37.0/0.58b0 (2025-09-11) From 7aac5b0d661c46847406edcc5a70541b267d03bd Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 14 Oct 2025 11:10:04 +0200 Subject: [PATCH 07/13] Feedback: drop warnings that have a deprecations --- .../sdk/_logs/_internal/__init__.py | 8 +- .../sdk/_logs/_internal/export/__init__.py | 8 -- .../export/in_memory_log_exporter.py | 9 +- opentelemetry-sdk/tests/logs/test_export.py | 98 ------------------- .../tests/logs/test_log_limits.py | 43 +------- .../tests/logs/test_log_record.py | 4 +- 6 files changed, 5 insertions(+), 165 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index f96d02870b6..f6152e62129 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -147,12 +147,6 @@ def __init__( OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, ) - warnings.warn( - "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", - LogDeprecatedInitWarning, - stacklevel=0, - ) - def __repr__(self): return f"{type(self).__name__}(max_attributes={self.max_attributes}, max_attribute_length={self.max_attribute_length})" @@ -370,7 +364,7 @@ def __init__( instrumentation_scope: InstrumentationScope, ): warnings.warn( - "LogData will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", + "LogData will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", LogDeprecatedInitWarning, stacklevel=0, ) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py index 2b60d729808..e632800c8cf 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/__init__.py @@ -17,7 +17,6 @@ import enum import logging import sys -import warnings from os import environ, linesep from typing import IO, Callable, Optional, Sequence @@ -29,7 +28,6 @@ ) from opentelemetry.sdk._logs import ( LogData, - LogDeprecatedInitWarning, LogRecord, LogRecordProcessor, ) @@ -99,12 +97,6 @@ def __init__( self.out = out self.formatter = formatter - warnings.warn( - "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", - LogDeprecatedInitWarning, - stacklevel=0, - ) - def export(self, batch: Sequence[LogData]): for data in batch: self.out.write(self.formatter(data.log_record)) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py index 0a94f66e535..68cb6b7389a 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/export/in_memory_log_exporter.py @@ -14,9 +14,8 @@ import threading import typing -import warnings -from opentelemetry.sdk._logs import LogData, LogDeprecatedInitWarning +from opentelemetry.sdk._logs import LogData from opentelemetry.sdk._logs.export import LogExporter, LogExportResult @@ -33,12 +32,6 @@ def __init__(self): self._lock = threading.Lock() self._stopped = False - warnings.warn( - "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", - LogDeprecatedInitWarning, - stacklevel=0, - ) - def clear(self) -> None: with self._lock: self._logs.clear() diff --git a/opentelemetry-sdk/tests/logs/test_export.py b/opentelemetry-sdk/tests/logs/test_export.py index 2d822d18386..4b8d98693c5 100644 --- a/opentelemetry-sdk/tests/logs/test_export.py +++ b/opentelemetry-sdk/tests/logs/test_export.py @@ -17,7 +17,6 @@ import os import time import unittest -import warnings from concurrent.futures import ThreadPoolExecutor from sys import version_info from unittest.mock import Mock, patch @@ -28,7 +27,6 @@ from opentelemetry.sdk import trace from opentelemetry.sdk._logs import ( LogData, - LogDeprecatedInitWarning, LoggerProvider, LoggingHandler, LogRecord, @@ -649,99 +647,3 @@ def formatter(record): # pylint: disable=unused-argument exporter.export([EMPTY_LOG]) mock_stdout.write.assert_called_once_with(mock_record_str) - - def test_console_log_exporter_deprecated_warning(self): - """Test that ConsoleLogExporter initialization emits a deprecation warning.""" - with warnings.catch_warnings(record=True) as cw: - warnings.simplefilter("always") - ConsoleLogExporter() - - # Check that at least one LogDeprecatedInitWarning, was emitted - console_warnings = [ - w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) - ] - self.assertGreater( - len(console_warnings), - 0, - "Expected at least one LogDeprecatedInitWarning", - ) - - # Check the message content of the warning - warning_message = str(console_warnings[0].message) - self.assertIn( - "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", - warning_message, - ) - - def test_console_log_exporter_deprecated_warning_once(self): - """Test that ConsoleLogExporter deprecation warning is only shown once due to simplefilter('once').""" - with warnings.catch_warnings(record=True) as cw: - # Multiple instantiations should only warn once due to simplefilter("once") - for _ in range(10): - ConsoleLogExporter() - - # Check that exactly one LogDeprecatedInitWarning was emitted - console_warnings = [ - w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) - ] - self.assertEqual( - len(console_warnings), - 1, - "Expected exactly one LogDeprecatedInitWarning due to simplefilter('once')", - ) - - # Check the message content - warning_message = str(console_warnings[0].message) - self.assertIn( - "ConsoleLogExporter will be deprecated in 1.39.0 and then renamed to ConsoleLogRecordExporter", - warning_message, - ) - - -class TestInMemoryLogExporterDeprecation(unittest.TestCase): - def test_in_memory_log_exporter_deprecated_warning(self): - """Test that InMemoryLogExporter initialization emits a deprecation warning.""" - with warnings.catch_warnings(record=True) as cw: - warnings.simplefilter("always") - InMemoryLogExporter() - - # Check that at least one LogDeprecatedInitWarning was emitted - in_memory_warnings = [ - w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) - ] - self.assertGreater( - len(in_memory_warnings), - 0, - "Expected at least one LogDeprecatedInitWarning", - ) - - # Check the message content of the warning - warning_message = str(in_memory_warnings[0].message) - self.assertIn( - "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", - warning_message, - ) - - def test_in_memory_log_exporter_deprecated_warning_once(self): - """Test that InMemoryLogExporter deprecation warning is only shown once due to simplefilter('once').""" - with warnings.catch_warnings(record=True) as cw: - # Multiple instantiations should only warn once due to simplefilter("once") - for _ in range(10): - InMemoryLogExporter() - - # Check that exactly one LogDeprecatedInitWarning was emitted - in_memory_warnings = [ - w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) - ] - self.assertEqual( - len(in_memory_warnings), - 1, - "Expected exactly one LogDeprecatedInitWarning due to simplefilter('once')", - ) - - # Check the message content - warning_message = str(in_memory_warnings[0].message) - self.assertIn( - "InMemoryLogExporter will be deprecated in 1.39.0 and then renamed to InMemoryLogRecordExporter", - warning_message, - ) diff --git a/opentelemetry-sdk/tests/logs/test_log_limits.py b/opentelemetry-sdk/tests/logs/test_log_limits.py index 5fda9f0b666..82a7ce9b4d6 100644 --- a/opentelemetry-sdk/tests/logs/test_log_limits.py +++ b/opentelemetry-sdk/tests/logs/test_log_limits.py @@ -13,10 +13,9 @@ # limitations under the License. import unittest -import warnings from unittest.mock import patch -from opentelemetry.sdk._logs import LogDeprecatedInitWarning, LogLimits +from opentelemetry.sdk._logs import LogLimits from opentelemetry.sdk._logs._internal import ( _DEFAULT_OTEL_ATTRIBUTE_COUNT_LIMIT, ) @@ -71,43 +70,3 @@ def test_invalid_env_vars_raise(self): str(error.exception), f"Unexpected error message for {env_var}={bad_value}", ) - - def test_log_limits_init_deprecated_warning(self): - """Test that LogLimits initialization emits a deprecation warning.""" - with warnings.catch_warnings(record=True) as cw: - warnings.simplefilter("always") - LogLimits() - - self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) - self.assertIn( - "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", - str(cw[-1].message), - ) - - def test_log_limits_init_deprecated_warning_with_params(self): - """Test that LogLimits initialization with parameters still emits a deprecation warning.""" - with warnings.catch_warnings(record=True) as cw: - warnings.simplefilter("always") - LogLimits(max_attributes=10, max_attribute_length=100) - - self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) - self.assertIn( - "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", - str(cw[-1].message), - ) - - def test_log_limits_init_deprecated_warning_once(self): - """Test that LogLimits deprecation warning is only shown once due to simplefilter('once').""" - with warnings.catch_warnings(record=True) as cw: - # Multiple instantiations should only warn once due to simplefilter("once") - for _ in range(10): - LogLimits() - - self.assertEqual(len(cw), 1) - self.assertIsInstance(cw[-1].message, LogDeprecatedInitWarning) - self.assertIn( - "LogLimits will be deprecated in 1.39.0 and then renamed to LogRecordLimits", - str(cw[-1].message), - ) diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index 651c4801cfd..922c45150f4 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -189,7 +189,7 @@ def test_log_record_context_deprecated_init_warning(self): for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] - self.assertEqual(len(context_deprecated_warnings), 3) + self.assertEqual(len(context_deprecated_warnings), 2) # Check we have the expected message once log_record_context_warning = [ @@ -209,7 +209,7 @@ def test_log_record_context_deprecated_init_warning(self): context_deprecated_warnings = [ w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) ] - self.assertEqual(len(context_deprecated_warnings), 2) + self.assertEqual(len(context_deprecated_warnings), 1) # Check we have no message log_record_context_warning = [ From 2d9e1596102d61adb1fdc11dcb5b3279abb539e2 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 14 Oct 2025 11:37:43 +0200 Subject: [PATCH 08/13] Update logrecord warning message --- .../src/opentelemetry/sdk/_logs/_internal/__init__.py | 2 +- opentelemetry-sdk/tests/logs/test_log_record.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index f6152e62129..c49821c391d 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -235,7 +235,7 @@ def __init__( # pylint:disable=too-many-locals event_name: str | None = None, ): warnings.warn( - "LogRecord will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", + "LogRecord will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", LogDeprecatedInitWarning, stacklevel=0, ) diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index 922c45150f4..a2c6d7f2399 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -240,7 +240,7 @@ def test_log_record_init_deprecated_warning(self): # Check the message content of the LogRecordInitDeprecatedWarning warning_message = str(log_record_init_warnings[0].message) self.assertIn( - "LogRecord will be substituted in 1.39.0 by ReadWriteLogRecord and ReadableLogRecord", + "LogRecord will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", warning_message, ) From 5d30eb621dcdb6573bff98243e6e74e80de6aefc Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Tue, 14 Oct 2025 17:14:13 +0200 Subject: [PATCH 09/13] Use default stacklevel --- .../src/opentelemetry/sdk/_logs/_internal/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index c49821c391d..8d0727b071b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -237,7 +237,6 @@ def __init__( # pylint:disable=too-many-locals warnings.warn( "LogRecord will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", LogDeprecatedInitWarning, - stacklevel=0, ) if not context: context = get_current() @@ -366,7 +365,6 @@ def __init__( warnings.warn( "LogData will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", LogDeprecatedInitWarning, - stacklevel=0, ) self.log_record = log_record self.instrumentation_scope = instrumentation_scope From 438bb7eb63570ac7e05ab3bc9412d08238be5a18 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Wed, 15 Oct 2025 14:34:08 +0200 Subject: [PATCH 10/13] Silence deprecation warnings from internal users --- .../sdk/_logs/_internal/__init__.py | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index 8d0727b071b..debec07e04b 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -735,25 +735,28 @@ def emit( and instrumentation info. """ - if not record: - record = LogRecord( - timestamp=timestamp, - observed_timestamp=observed_timestamp, - context=context, - severity_text=severity_text, - severity_number=severity_number, - body=body, - attributes=attributes, - event_name=event_name, - resource=self._resource, - ) - elif not isinstance(record, LogRecord): - # pylint:disable=protected-access - record = LogRecord._from_api_log_record( - record=record, resource=self._resource - ) + # silence deprecation warnings from internal users + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=LogDeprecatedInitWarning) + if not record: + record = LogRecord( + timestamp=timestamp, + observed_timestamp=observed_timestamp, + context=context, + severity_text=severity_text, + severity_number=severity_number, + body=body, + attributes=attributes, + event_name=event_name, + resource=self._resource, + ) + elif not isinstance(record, LogRecord): + # pylint:disable=protected-access + record = LogRecord._from_api_log_record( + record=record, resource=self._resource + ) - log_data = LogData(record, self._instrumentation_scope) + log_data = LogData(record, self._instrumentation_scope) self._multi_log_record_processor.on_emit(log_data) From 24d191404d8645f6ab9563c539345d8df5ac5f53 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Wed, 15 Oct 2025 14:48:55 +0200 Subject: [PATCH 11/13] Add test for logdata warnings --- .../tests/logs/test_log_record.py | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/opentelemetry-sdk/tests/logs/test_log_record.py b/opentelemetry-sdk/tests/logs/test_log_record.py index a2c6d7f2399..49c9c549393 100644 --- a/opentelemetry-sdk/tests/logs/test_log_record.py +++ b/opentelemetry-sdk/tests/logs/test_log_record.py @@ -21,12 +21,14 @@ from opentelemetry.attributes import BoundedAttributes from opentelemetry.context import get_current from opentelemetry.sdk._logs import ( + LogData, LogDeprecatedInitWarning, LogDroppedAttributesWarning, LogLimits, LogRecord, ) from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.util.instrumentation import InstrumentationScope from opentelemetry.trace.span import TraceFlags @@ -222,7 +224,7 @@ def test_log_record_context_deprecated_init_warning(self): self.assertEqual(len(log_record_context_warning), 0) def test_log_record_init_deprecated_warning(self): - """Test that LogRecord initialization emits a LogRecordInitDeprecatedWarning.""" + """Test that LogRecord initialization emits a LogDeprecatedInitWarning.""" with warnings.catch_warnings(record=True) as cw: warnings.simplefilter("always") LogRecord() @@ -234,10 +236,10 @@ def test_log_record_init_deprecated_warning(self): self.assertGreater( len(log_record_init_warnings), 0, - "Expected at least one LogRecordInitDeprecatedWarning", + "Expected at least one LogDeprecatedInitWarning", ) - # Check the message content of the LogRecordInitDeprecatedWarning + # Check the message content of the LogDeprecatedInitWarning warning_message = str(log_record_init_warnings[0].message) self.assertIn( "LogRecord will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", @@ -277,3 +279,33 @@ def test_log_record_from_api_log_record(self): self.assertEqual(record.attributes, {"a": "b"}) self.assertEqual(record.event_name, "an.event") self.assertEqual(record.resource, resource) + + +class TestLogData(unittest.TestCase): + def test_init_deprecated_warning(self): + """Test that LogData initialization emits a LogDeprecatedInitWarning.""" + log_record = LogRecord() + + with warnings.catch_warnings(record=True) as cw: + warnings.simplefilter("always") + LogData( + log_record=log_record, + instrumentation_scope=InstrumentationScope("foo", "bar"), + ) + + # Check that at least one LogDeprecatedInitWarning was emitted + init_warnings = [ + w for w in cw if isinstance(w.message, LogDeprecatedInitWarning) + ] + self.assertGreater( + len(init_warnings), + 0, + "Expected at least one LogDeprecatedInitWarning", + ) + + # Check the message content of the LogDeprecatedInitWarning + warning_message = str(init_warnings[0].message) + self.assertIn( + "LogData will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", + warning_message, + ) From b09f4f278ee1d0c286f7bd10f6c1877df03c52e4 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Wed, 15 Oct 2025 17:29:37 +0200 Subject: [PATCH 12/13] WIP NOT WORKING capture deprecations warnings in EventLogger.emit --- .../src/opentelemetry/sdk/_events/__init__.py | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py index c427a48e2f8..0a88936ea11 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_events/__init__.py @@ -11,7 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import logging +import warnings from time import time_ns from typing import Optional @@ -20,7 +22,12 @@ from opentelemetry._events import EventLogger as APIEventLogger from opentelemetry._events import EventLoggerProvider as APIEventLoggerProvider from opentelemetry._logs import NoOpLogger, SeverityNumber, get_logger_provider -from opentelemetry.sdk._logs import Logger, LoggerProvider, LogRecord +from opentelemetry.sdk._logs import ( + LogDeprecatedInitWarning, + Logger, + LoggerProvider, + LogRecord, +) from opentelemetry.util.types import _ExtendedAttributes _logger = logging.getLogger(__name__) @@ -50,18 +57,23 @@ def emit(self, event: Event) -> None: # Do nothing if SDK is disabled return span_context = trace.get_current_span().get_span_context() - log_record = LogRecord( - timestamp=event.timestamp or time_ns(), - observed_timestamp=None, - trace_id=event.trace_id or span_context.trace_id, - span_id=event.span_id or span_context.span_id, - trace_flags=event.trace_flags or span_context.trace_flags, - severity_text=None, - severity_number=event.severity_number or SeverityNumber.INFO, - body=event.body, - resource=getattr(self._logger, "resource", None), - attributes=event.attributes, - ) + + # silence deprecation warnings from internal users + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=LogDeprecatedInitWarning) + + log_record = LogRecord( + timestamp=event.timestamp or time_ns(), + observed_timestamp=None, + trace_id=event.trace_id or span_context.trace_id, + span_id=event.span_id or span_context.span_id, + trace_flags=event.trace_flags or span_context.trace_flags, + severity_text=None, + severity_number=event.severity_number or SeverityNumber.INFO, + body=event.body, + resource=getattr(self._logger, "resource", None), + attributes=event.attributes, + ) self._logger.emit(log_record) From ad1d688f449a03db3878ad333edff1098eee4165 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Thu, 16 Oct 2025 09:29:42 +0200 Subject: [PATCH 13/13] Use stacklevel=2 for getting the caller --- .../src/opentelemetry/sdk/_logs/_internal/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py index debec07e04b..9e2d3f7d7f3 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/_logs/_internal/__init__.py @@ -237,6 +237,7 @@ def __init__( # pylint:disable=too-many-locals warnings.warn( "LogRecord will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", LogDeprecatedInitWarning, + stacklevel=2, ) if not context: context = get_current() @@ -365,6 +366,7 @@ def __init__( warnings.warn( "LogData will be removed in 1.39.0 and replaced by ReadWriteLogRecord and ReadableLogRecord", LogDeprecatedInitWarning, + stacklevel=2, ) self.log_record = log_record self.instrumentation_scope = instrumentation_scope