From af659c7650d0ae99d11184edfe1d8d9237d5272c Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 11:25:48 +0200 Subject: [PATCH 1/7] feat(logs): Add top-level enable_logs option --- sentry_sdk/client.py | 6 +++--- sentry_sdk/consts.py | 5 ++++- sentry_sdk/integrations/logging.py | 4 ++-- sentry_sdk/integrations/loguru.py | 4 ++-- sentry_sdk/logger.py | 13 ++++++++++++- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index dca39beab8..72b98b855b 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -37,6 +37,7 @@ ) from sentry_sdk.integrations import _DEFAULT_INTEGRATIONS, setup_integrations from sentry_sdk.integrations.dedupe import DedupeIntegration +from sentry_sdk.logger import has_logs_enabled from sentry_sdk.sessions import SessionFlusher from sentry_sdk.envelope import Envelope from sentry_sdk.profiler.continuous_profiler import setup_continuous_profiler @@ -382,7 +383,7 @@ def _capture_envelope(envelope): ) self.log_batcher = None - if experiments.get("enable_logs", False): + if has_logs_enabled(self.options): from sentry_sdk._log_batcher import LogBatcher self.log_batcher = LogBatcher(capture_func=_capture_envelope) @@ -899,8 +900,7 @@ def capture_event( def _capture_experimental_log(self, log): # type: (Log) -> None - logs_enabled = self.options["_experiments"].get("enable_logs", False) - if not logs_enabled: + if not has_logs_enabled(self.options): return current_scope = sentry_sdk.get_current_scope() diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index dd9055b869..674661ff3a 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -798,6 +798,7 @@ def __init__( custom_repr=None, # type: Optional[Callable[..., Optional[str]]] add_full_stack=DEFAULT_ADD_FULL_STACK, # type: bool max_stack_frames=DEFAULT_MAX_STACK_FRAMES, # type: Optional[int] + enable_logs=False, # type: bool ): # type: (...) -> None """Initialize the Sentry SDK with the given parameters. All parameters described here can be used in a call to `sentry_sdk.init()`. @@ -1168,7 +1169,6 @@ def __init__( :param profile_session_sample_rate: - :param enable_tracing: :param propagate_traces: @@ -1179,6 +1179,9 @@ def __init__( :param instrumenter: + :param enable_logs: Set `enable_logs` to True to enable the SDK to emit + Sentry logs. Defaults to False. + :param _experiments: """ pass diff --git a/sentry_sdk/integrations/logging.py b/sentry_sdk/integrations/logging.py index a50512f622..2a0f57c2b2 100644 --- a/sentry_sdk/integrations/logging.py +++ b/sentry_sdk/integrations/logging.py @@ -5,7 +5,7 @@ import sentry_sdk from sentry_sdk.client import BaseClient -from sentry_sdk.logger import _log_level_to_otel +from sentry_sdk.logger import _log_level_to_otel, has_logs_enabled from sentry_sdk.utils import ( safe_repr, to_string, @@ -344,7 +344,7 @@ def emit(self, record): if not client.is_active(): return - if not client.options["_experiments"].get("enable_logs", False): + if not has_logs_enabled(client.options): return self._capture_log_from_record(client, record) diff --git a/sentry_sdk/integrations/loguru.py b/sentry_sdk/integrations/loguru.py index df3ecf161a..88359422f2 100644 --- a/sentry_sdk/integrations/loguru.py +++ b/sentry_sdk/integrations/loguru.py @@ -7,7 +7,7 @@ EventHandler, _BaseHandler, ) -from sentry_sdk.logger import _log_level_to_otel +from sentry_sdk.logger import _log_level_to_otel, has_logs_enabled from typing import TYPE_CHECKING @@ -151,7 +151,7 @@ def loguru_sentry_logs_handler(message): if not client.is_active(): return - if not client.options["_experiments"].get("enable_logs", False): + if not has_logs_enabled(client.options): return record = message.record diff --git a/sentry_sdk/logger.py b/sentry_sdk/logger.py index c18cf91ff2..38f0fb325d 100644 --- a/sentry_sdk/logger.py +++ b/sentry_sdk/logger.py @@ -1,7 +1,7 @@ # NOTE: this is the logger sentry exposes to users, not some generic logger. import functools import time -from typing import Any +from typing import Any, Optional from sentry_sdk import get_client from sentry_sdk.utils import safe_repr @@ -81,3 +81,14 @@ def _log_level_to_otel(level, mapping): return otel_severity_number, _otel_severity_text(otel_severity_number) return 0, "default" + + +def has_logs_enabled(options): + # type: (Optional[dict[str, Any]]) -> bool + if options is None: + return False + + return bool( + options.get("enable_logs", False) + or options["_experiments"].get("enable_logs", False) + ) From e3d693c2b0ff8d2c41624f2ddbb264b778244cd7 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 11:27:12 +0200 Subject: [PATCH 2/7] change in tests --- tests/integrations/logging/test_logging.py | 16 ++++++++-------- tests/integrations/loguru/test_loguru.py | 18 +++++++++--------- tests/test_logs.py | 16 ++++++++-------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/integrations/logging/test_logging.py b/tests/integrations/logging/test_logging.py index 6ef4ae371b..7ecdf42500 100644 --- a/tests/integrations/logging/test_logging.py +++ b/tests/integrations/logging/test_logging.py @@ -304,7 +304,7 @@ def test_sentry_logs_warning(sentry_init, capture_envelopes): """ The python logger module should create 'warn' sentry logs if the flag is on. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") @@ -329,7 +329,7 @@ def test_sentry_logs_debug(sentry_init, capture_envelopes): """ The python logger module should not create 'debug' sentry logs if the flag is on by default """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") @@ -344,7 +344,7 @@ def test_no_log_infinite_loop(sentry_init, capture_envelopes): If 'debug' mode is true, and you set a low log level in the logging integration, there should be no infinite loops. """ sentry_init( - _experiments={"enable_logs": True}, + enable_logs=True, integrations=[LoggingIntegration(sentry_logs_level=logging.DEBUG)], debug=True, ) @@ -361,7 +361,7 @@ def test_logging_errors(sentry_init, capture_envelopes): """ The python logger module should be able to log errors without erroring """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") @@ -396,7 +396,7 @@ def test_log_strips_project_root(sentry_init, capture_envelopes): The python logger should strip project roots from the log record path """ sentry_init( - _experiments={"enable_logs": True}, + enable_logs=True, project_root="/custom/test", ) envelopes = capture_envelopes() @@ -425,7 +425,7 @@ def test_logger_with_all_attributes(sentry_init, capture_envelopes): """ The python logger should be able to log all attributes, including extra data. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") @@ -498,7 +498,7 @@ def test_sentry_logs_named_parameters(sentry_init, capture_envelopes): """ The python logger module should capture named parameters from dictionary arguments in Sentry logs. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") @@ -543,7 +543,7 @@ def test_sentry_logs_named_parameters_complex_values(sentry_init, capture_envelo """ The python logger module should handle complex values in named parameters using safe_repr. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") diff --git a/tests/integrations/loguru/test_loguru.py b/tests/integrations/loguru/test_loguru.py index c120d1d7e2..38093d24cb 100644 --- a/tests/integrations/loguru/test_loguru.py +++ b/tests/integrations/loguru/test_loguru.py @@ -141,7 +141,7 @@ def test_sentry_logs_warning( uninstall_integration("loguru") request.addfinalizer(logger.remove) - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() logger.warning("this is {} a {}", "just", "template") @@ -165,7 +165,7 @@ def test_sentry_logs_debug( uninstall_integration("loguru") request.addfinalizer(logger.remove) - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() logger.debug("this is %s a template %s", "1", "2") @@ -182,7 +182,7 @@ def test_sentry_log_levels( sentry_init( integrations=[LoguruIntegration(sentry_logs_level=LoggingLevels.SUCCESS)], - _experiments={"enable_logs": True}, + enable_logs=True, ) envelopes = capture_envelopes() @@ -216,7 +216,7 @@ def test_disable_loguru_logs( sentry_init( integrations=[LoguruIntegration(sentry_logs_level=None)], - _experiments={"enable_logs": True}, + enable_logs=True, ) envelopes = capture_envelopes() @@ -267,7 +267,7 @@ def test_no_log_infinite_loop( request.addfinalizer(logger.remove) sentry_init( - _experiments={"enable_logs": True}, + enable_logs=True, integrations=[LoguruIntegration(sentry_logs_level=LoggingLevels.DEBUG)], debug=True, ) @@ -284,7 +284,7 @@ def test_logging_errors(sentry_init, capture_envelopes, uninstall_integration, r uninstall_integration("loguru") request.addfinalizer(logger.remove) - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() logger.error(Exception("test exc 1")) @@ -313,7 +313,7 @@ def test_log_strips_project_root( request.addfinalizer(logger.remove) sentry_init( - _experiments={"enable_logs": True}, + enable_logs=True, project_root="/custom/test", ) envelopes = capture_envelopes() @@ -362,7 +362,7 @@ def test_log_keeps_full_path_if_not_in_project_root( request.addfinalizer(logger.remove) sentry_init( - _experiments={"enable_logs": True}, + enable_logs=True, project_root="/custom/test", ) envelopes = capture_envelopes() @@ -410,7 +410,7 @@ def test_logger_with_all_attributes( uninstall_integration("loguru") request.addfinalizer(logger.remove) - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() logger.warning("log #{}", 1) diff --git a/tests/test_logs.py b/tests/test_logs.py index a2f412dcb0..c67d2a6b3f 100644 --- a/tests/test_logs.py +++ b/tests/test_logs.py @@ -80,7 +80,7 @@ def test_logs_disabled_by_default(sentry_init, capture_envelopes): @minimum_python_37 def test_logs_basics(sentry_init, capture_envelopes): - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() sentry_sdk.logger.trace("This is a 'trace' log...") @@ -163,7 +163,7 @@ def test_logs_attributes(sentry_init, capture_envelopes): """ Passing arbitrary attributes to log messages. """ - sentry_init(_experiments={"enable_logs": True}, server_name="test-server") + sentry_init(enable_logs=True, server_name="test-server") envelopes = capture_envelopes() attrs = { @@ -196,7 +196,7 @@ def test_logs_message_params(sentry_init, capture_envelopes): """ This is the official way of how to pass vars to log messages. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() sentry_sdk.logger.warning("The recorded value was '{int_var}'", int_var=1) @@ -239,7 +239,7 @@ def test_logs_tied_to_transactions(sentry_init, capture_envelopes): """ Log messages are also tied to transactions. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() with sentry_sdk.start_transaction(name="test-transaction") as trx: @@ -255,7 +255,7 @@ def test_logs_tied_to_spans(sentry_init, capture_envelopes): """ Log messages are also tied to spans. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() with sentry_sdk.start_transaction(name="test-transaction"): @@ -271,7 +271,7 @@ def test_auto_flush_logs_after_100(sentry_init, capture_envelopes): """ If you log >100 logs, it should automatically trigger a flush. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") @@ -288,7 +288,7 @@ def test_auto_flush_logs_after_100(sentry_init, capture_envelopes): def test_log_user_attributes(sentry_init, capture_envelopes): """User attributes are sent if enable_logs is True.""" - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) sentry_sdk.set_user({"id": "1", "email": "test@example.com", "username": "test"}) envelopes = capture_envelopes() @@ -314,7 +314,7 @@ def test_auto_flush_logs_after_5s(sentry_init, capture_envelopes): """ If you log a single log, it should automatically flush after 5 seconds, at most 10 seconds. """ - sentry_init(_experiments={"enable_logs": True}) + sentry_init(enable_logs=True) envelopes = capture_envelopes() python_logger = logging.Logger("test-logger") From 47b1645baa7bd56e6236d0d82e412a9465f12166 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 11:38:38 +0200 Subject: [PATCH 3/7] before_send_log, compat tests --- sentry_sdk/client.py | 4 +-- sentry_sdk/consts.py | 1 + sentry_sdk/logger.py | 13 +++++++++- tests/test_logs.py | 60 ++++++++++++++++++++++++++++++++++++++------ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 72b98b855b..5198ead3f4 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -37,7 +37,7 @@ ) from sentry_sdk.integrations import _DEFAULT_INTEGRATIONS, setup_integrations from sentry_sdk.integrations.dedupe import DedupeIntegration -from sentry_sdk.logger import has_logs_enabled +from sentry_sdk.logger import has_logs_enabled, get_before_send_log from sentry_sdk.sessions import SessionFlusher from sentry_sdk.envelope import Envelope from sentry_sdk.profiler.continuous_profiler import setup_continuous_profiler @@ -955,7 +955,7 @@ def _capture_experimental_log(self, log): f'[Sentry Logs] [{log.get("severity_text")}] {log.get("body")}' ) - before_send_log = self.options["_experiments"].get("before_send_log") + before_send_log = get_before_send_log(self.options) if before_send_log is not None: log = before_send_log(log, {}) if log is None: diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 674661ff3a..4a6e11064a 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -799,6 +799,7 @@ def __init__( add_full_stack=DEFAULT_ADD_FULL_STACK, # type: bool max_stack_frames=DEFAULT_MAX_STACK_FRAMES, # type: Optional[int] enable_logs=False, # type: bool + before_send_log=None, # type: Optional[Callable[[Log, Hint], Optional[Log]]] ): # type: (...) -> None """Initialize the Sentry SDK with the given parameters. All parameters described here can be used in a call to `sentry_sdk.init()`. diff --git a/sentry_sdk/logger.py b/sentry_sdk/logger.py index 38f0fb325d..1291ddab84 100644 --- a/sentry_sdk/logger.py +++ b/sentry_sdk/logger.py @@ -1,10 +1,11 @@ # NOTE: this is the logger sentry exposes to users, not some generic logger. import functools import time -from typing import Any, Optional +from typing import Any, Callable, Optional from sentry_sdk import get_client from sentry_sdk.utils import safe_repr +from sentry_sdk.types import Log, Hint OTEL_RANGES = [ # ((severity level range), severity text) @@ -92,3 +93,13 @@ def has_logs_enabled(options): options.get("enable_logs", False) or options["_experiments"].get("enable_logs", False) ) + + +def get_before_send_log(options): + # type: (Optional[dict[str, Any]]) -> Optional[Callable[[Log, Hint], Optional[Log]]] + if options is None: + return None + + return options.get("before_send_log") or options["_experiments"].get( + "before_send_log" + ) diff --git a/tests/test_logs.py b/tests/test_logs.py index c67d2a6b3f..b2578d83d5 100644 --- a/tests/test_logs.py +++ b/tests/test_logs.py @@ -111,11 +111,29 @@ def test_logs_basics(sentry_init, capture_envelopes): assert logs[5].get("severity_number") == 21 +@minimum_python_37 +def test_logs_experimental_option_still_works(sentry_init, capture_envelopes): + sentry_init(_experiments={"enable_logs": True}) + envelopes = capture_envelopes() + + sentry_sdk.logger.error("This is an error log...") + + get_client().flush() + + logs = envelopes_to_logs(envelopes) + assert len(logs) == 1 + + assert logs[0].get("severity_text") == "error" + assert logs[0].get("severity_number") == 17 + + @minimum_python_37 def test_logs_before_send_log(sentry_init, capture_envelopes): - before_log_called = [False] + before_log_called = False def _before_log(record, hint): + nonlocal before_log_called + assert set(record.keys()) == { "severity_text", "severity_number", @@ -128,15 +146,13 @@ def _before_log(record, hint): if record["severity_text"] in ["fatal", "error"]: return None - before_log_called[0] = True + before_log_called = True return record sentry_init( - _experiments={ - "enable_logs": True, - "before_send_log": _before_log, - } + enable_logs=True, + before_send_log=_before_log, ) envelopes = capture_envelopes() @@ -155,7 +171,37 @@ def _before_log(record, hint): assert logs[1]["severity_text"] == "debug" assert logs[2]["severity_text"] == "info" assert logs[3]["severity_text"] == "warn" - assert before_log_called[0] + assert before_log_called is True + + +@minimum_python_37 +def test_logs_before_send_log_experimental_option_still_works( + sentry_init, capture_envelopes +): + before_log_called = False + + def _before_log(record, hint): + nonlocal before_log_called + before_log_called = True + + return record + + sentry_init( + enable_logs=True, + _experiments={ + "before_send_log": _before_log, + }, + ) + envelopes = capture_envelopes() + + sentry_sdk.logger.error("This is an error log...") + + get_client().flush() + logs = envelopes_to_logs(envelopes) + assert len(logs) == 1 + + assert logs[0]["severity_text"] == "error" + assert before_log_called is True @minimum_python_37 From 2ea1bd76c3e97eeb76d373eec063830cc3321f28 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 11:41:15 +0200 Subject: [PATCH 4/7] comment --- sentry_sdk/consts.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 4a6e11064a..fbfa28d6bf 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -1183,6 +1183,11 @@ def __init__( :param enable_logs: Set `enable_logs` to True to enable the SDK to emit Sentry logs. Defaults to False. + :param before_send_log: An optional function to modify or filter out logs + before they're sent to Sentry. Any modifications to the log in this + function will be retained. If the function returns None, the log will + not be sent to Sentry. + :param _experiments: """ pass From 9ecb4f775c3c356c0fea56e87d382d0331c34c7f Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 11:45:31 +0200 Subject: [PATCH 5/7] circ imports --- sentry_sdk/client.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 5198ead3f4..b6a7171107 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -37,7 +37,6 @@ ) from sentry_sdk.integrations import _DEFAULT_INTEGRATIONS, setup_integrations from sentry_sdk.integrations.dedupe import DedupeIntegration -from sentry_sdk.logger import has_logs_enabled, get_before_send_log from sentry_sdk.sessions import SessionFlusher from sentry_sdk.envelope import Envelope from sentry_sdk.profiler.continuous_profiler import setup_continuous_profiler @@ -383,6 +382,9 @@ def _capture_envelope(envelope): ) self.log_batcher = None + + from sentry_sdk.logger import has_logs_enabled + if has_logs_enabled(self.options): from sentry_sdk._log_batcher import LogBatcher @@ -900,6 +902,8 @@ def capture_event( def _capture_experimental_log(self, log): # type: (Log) -> None + from sentry_sdk.logger import get_before_send_log, has_logs_enabled + if not has_logs_enabled(self.options): return From 4f76f120409ae76ca0b2e6d7b2a44e680705b019 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 11:55:01 +0200 Subject: [PATCH 6/7] mypy, sigh --- sentry_sdk/client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index b6a7171107..11b11449c1 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -901,10 +901,10 @@ def capture_event( return return_value def _capture_experimental_log(self, log): - # type: (Log) -> None + # type: (Optional[Log]) -> None from sentry_sdk.logger import get_before_send_log, has_logs_enabled - if not has_logs_enabled(self.options): + if not has_logs_enabled(self.options) or log is None: return current_scope = sentry_sdk.get_current_scope() @@ -962,6 +962,7 @@ def _capture_experimental_log(self, log): before_send_log = get_before_send_log(self.options) if before_send_log is not None: log = before_send_log(log, {}) + if log is None: return From 46f6dc3a186c2b48ac6ad19c84be04e604c40dd2 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Wed, 30 Jul 2025 12:00:33 +0200 Subject: [PATCH 7/7] move compat funcs to utils, no circ imports that way --- sentry_sdk/client.py | 6 ++---- sentry_sdk/integrations/logging.py | 3 ++- sentry_sdk/integrations/loguru.py | 3 ++- sentry_sdk/logger.py | 24 +----------------------- sentry_sdk/utils.py | 23 ++++++++++++++++++++++- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/sentry_sdk/client.py b/sentry_sdk/client.py index 11b11449c1..5d584a5537 100644 --- a/sentry_sdk/client.py +++ b/sentry_sdk/client.py @@ -23,6 +23,8 @@ handle_in_app, is_gevent, logger, + get_before_send_log, + has_logs_enabled, ) from sentry_sdk.serializer import serialize from sentry_sdk.tracing import trace @@ -383,8 +385,6 @@ def _capture_envelope(envelope): self.log_batcher = None - from sentry_sdk.logger import has_logs_enabled - if has_logs_enabled(self.options): from sentry_sdk._log_batcher import LogBatcher @@ -902,8 +902,6 @@ def capture_event( def _capture_experimental_log(self, log): # type: (Optional[Log]) -> None - from sentry_sdk.logger import get_before_send_log, has_logs_enabled - if not has_logs_enabled(self.options) or log is None: return diff --git a/sentry_sdk/integrations/logging.py b/sentry_sdk/integrations/logging.py index 2a0f57c2b2..15ff2ed233 100644 --- a/sentry_sdk/integrations/logging.py +++ b/sentry_sdk/integrations/logging.py @@ -5,13 +5,14 @@ import sentry_sdk from sentry_sdk.client import BaseClient -from sentry_sdk.logger import _log_level_to_otel, has_logs_enabled +from sentry_sdk.logger import _log_level_to_otel from sentry_sdk.utils import ( safe_repr, to_string, event_from_exception, current_stacktrace, capture_internal_exceptions, + has_logs_enabled, ) from sentry_sdk.integrations import Integration diff --git a/sentry_sdk/integrations/loguru.py b/sentry_sdk/integrations/loguru.py index 88359422f2..b910b9a407 100644 --- a/sentry_sdk/integrations/loguru.py +++ b/sentry_sdk/integrations/loguru.py @@ -7,7 +7,8 @@ EventHandler, _BaseHandler, ) -from sentry_sdk.logger import _log_level_to_otel, has_logs_enabled +from sentry_sdk.logger import _log_level_to_otel +from sentry_sdk.utils import has_logs_enabled from typing import TYPE_CHECKING diff --git a/sentry_sdk/logger.py b/sentry_sdk/logger.py index 1291ddab84..c18cf91ff2 100644 --- a/sentry_sdk/logger.py +++ b/sentry_sdk/logger.py @@ -1,11 +1,10 @@ # NOTE: this is the logger sentry exposes to users, not some generic logger. import functools import time -from typing import Any, Callable, Optional +from typing import Any from sentry_sdk import get_client from sentry_sdk.utils import safe_repr -from sentry_sdk.types import Log, Hint OTEL_RANGES = [ # ((severity level range), severity text) @@ -82,24 +81,3 @@ def _log_level_to_otel(level, mapping): return otel_severity_number, _otel_severity_text(otel_severity_number) return 0, "default" - - -def has_logs_enabled(options): - # type: (Optional[dict[str, Any]]) -> bool - if options is None: - return False - - return bool( - options.get("enable_logs", False) - or options["_experiments"].get("enable_logs", False) - ) - - -def get_before_send_log(options): - # type: (Optional[dict[str, Any]]) -> Optional[Callable[[Log, Hint], Optional[Log]]] - if options is None: - return None - - return options.get("before_send_log") or options["_experiments"].get( - "before_send_log" - ) diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index 9c6f2cfc3b..b0f3fa4a4c 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -59,7 +59,7 @@ from gevent.hub import Hub - from sentry_sdk._types import Event, ExcInfo + from sentry_sdk._types import Event, ExcInfo, Log, Hint P = ParamSpec("P") R = TypeVar("R") @@ -1984,3 +1984,24 @@ def serialize_item(item): return json.dumps(serialized, default=str) except Exception: return str(data) + + +def has_logs_enabled(options): + # type: (Optional[dict[str, Any]]) -> bool + if options is None: + return False + + return bool( + options.get("enable_logs", False) + or options["_experiments"].get("enable_logs", False) + ) + + +def get_before_send_log(options): + # type: (Optional[dict[str, Any]]) -> Optional[Callable[[Log, Hint], Optional[Log]]] + if options is None: + return None + + return options.get("before_send_log") or options["_experiments"].get( + "before_send_log" + )