Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions sentry_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -382,7 +384,8 @@ 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)
Expand Down Expand Up @@ -898,9 +901,8 @@ def capture_event(
return return_value

def _capture_experimental_log(self, log):
# type: (Log) -> None
logs_enabled = self.options["_experiments"].get("enable_logs", False)
if not logs_enabled:
# type: (Optional[Log]) -> None
if not has_logs_enabled(self.options) or log is None:
Comment on lines +904 to +905
Copy link
Contributor Author

@sentrivana sentrivana Jul 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is here because mypy was complaining about log not being Optional on line 962 (in the new diff) and the get_before_send_log function potentially returning None 🙄

return

current_scope = sentry_sdk.get_current_scope()
Expand Down Expand Up @@ -955,9 +957,10 @@ 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:
return

Expand Down
11 changes: 10 additions & 1 deletion sentry_sdk/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,8 @@ 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
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()`.
Expand Down Expand Up @@ -1168,7 +1170,6 @@ def __init__(

:param profile_session_sample_rate:


:param enable_tracing:

:param propagate_traces:
Expand All @@ -1179,6 +1180,14 @@ def __init__(

:param instrumenter:

: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
Expand Down
3 changes: 2 additions & 1 deletion sentry_sdk/integrations/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
event_from_exception,
current_stacktrace,
capture_internal_exceptions,
has_logs_enabled,
)
from sentry_sdk.integrations import Integration

Expand Down Expand Up @@ -344,7 +345,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)
Expand Down
3 changes: 2 additions & 1 deletion sentry_sdk/integrations/loguru.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
_BaseHandler,
)
from sentry_sdk.logger import _log_level_to_otel
from sentry_sdk.utils import has_logs_enabled

from typing import TYPE_CHECKING

Expand Down Expand Up @@ -151,7 +152,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
Expand Down
23 changes: 22 additions & 1 deletion sentry_sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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"
)
16 changes: 8 additions & 8 deletions tests/integrations/logging/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -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,
)
Expand All @@ -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")
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand Down
18 changes: 9 additions & 9 deletions tests/integrations/loguru/test_loguru.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -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()

Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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,
)
Expand All @@ -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"))
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand Down
Loading
Loading