Skip to content

fix(ourlogs): Use repr instead of json for message and arguments #4227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 2, 2025
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
12 changes: 5 additions & 7 deletions sentry_sdk/integrations/logging.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import json
import logging
from datetime import datetime, timezone
from fnmatch import fnmatch

import sentry_sdk
from sentry_sdk.client import BaseClient
from sentry_sdk.utils import (
safe_repr,
to_string,
event_from_exception,
current_stacktrace,
Expand Down Expand Up @@ -358,16 +358,14 @@ def _capture_log_from_record(client, record):
# type: (BaseClient, LogRecord) -> None
scope = sentry_sdk.get_current_scope()
otel_severity_number, otel_severity_text = _python_level_to_otel(record.levelno)
attrs = {
"sentry.message.template": (
record.msg if isinstance(record.msg, str) else json.dumps(record.msg)
),
} # type: dict[str, str | bool | float | int]
attrs = {} # type: dict[str, str | bool | float | int]
if isinstance(record.msg, str):
attrs["sentry.message.template"] = record.msg
if record.args is not None:
if isinstance(record.args, tuple):
for i, arg in enumerate(record.args):
attrs[f"sentry.message.parameters.{i}"] = (
arg if isinstance(arg, str) else json.dumps(arg)
arg if isinstance(arg, str) else safe_repr(arg)
)
if record.lineno:
attrs["code.line.number"] = record.lineno
Expand Down
38 changes: 38 additions & 0 deletions tests/test_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,41 @@ def test_no_log_infinite_loop(sentry_init, capture_envelopes):
python_logger.debug("this is %s a template %s", "1", "2")

assert len(envelopes) == 1


@minimum_python_37
def test_logging_errors(sentry_init, capture_envelopes):
"""
The python logger module should be able to log errors without erroring
"""
sentry_init(_experiments={"enable_sentry_logs": True})
envelopes = capture_envelopes()

python_logger = logging.Logger("test-logger")
python_logger.error(Exception("test exc 1"))
python_logger.error("error is %s", Exception("test exc 2"))

error_event_1 = envelopes[0].items[0].payload.json
assert error_event_1["level"] == "error"

log_event_1 = envelopes[1].items[0].payload.json
assert log_event_1["severityText"] == "error"
# When only logging an exception, there is no "sentry.message.template" or "sentry.message.parameters.0"
assert len(log_event_1["attributes"]) == 10
assert log_event_1["attributes"][0]["key"] == "code.line.number"

error_event_2 = envelopes[2].items[0].payload.json
assert error_event_2["level"] == "error"

log_event_2 = envelopes[3].items[0].payload.json
assert log_event_2["severityText"] == "error"
assert len(log_event_2["attributes"]) == 12
assert log_event_2["attributes"][0]["key"] == "sentry.message.template"
assert log_event_2["attributes"][0]["value"] == {"stringValue": "error is %s"}
assert log_event_2["attributes"][1]["key"] == "sentry.message.parameters.0"
assert log_event_2["attributes"][1]["value"] == {
"stringValue": "Exception('test exc 2')"
}
assert log_event_2["attributes"][2]["key"] == "code.line.number"

assert len(envelopes) == 4
Loading