Skip to content

Commit 8b40aa0

Browse files
fix(ourlogs): Use repr instead of json for message and arguments (#4227)
Currently if you do something like ``` python_logger = logging.Logger("test-logger") python_logger.error(Exception("test exc")) ``` It will error, because Exception is not JSON serializable. --------- Co-authored-by: Anton Pirker <[email protected]>
1 parent 2dde2fe commit 8b40aa0

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

sentry_sdk/integrations/logging.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import json
21
import logging
32
from datetime import datetime, timezone
43
from fnmatch import fnmatch
54

65
import sentry_sdk
76
from sentry_sdk.client import BaseClient
87
from sentry_sdk.utils import (
8+
safe_repr,
99
to_string,
1010
event_from_exception,
1111
current_stacktrace,
@@ -358,16 +358,14 @@ def _capture_log_from_record(client, record):
358358
# type: (BaseClient, LogRecord) -> None
359359
scope = sentry_sdk.get_current_scope()
360360
otel_severity_number, otel_severity_text = _python_level_to_otel(record.levelno)
361-
attrs = {
362-
"sentry.message.template": (
363-
record.msg if isinstance(record.msg, str) else json.dumps(record.msg)
364-
),
365-
} # type: dict[str, str | bool | float | int]
361+
attrs = {} # type: dict[str, str | bool | float | int]
362+
if isinstance(record.msg, str):
363+
attrs["sentry.message.template"] = record.msg
366364
if record.args is not None:
367365
if isinstance(record.args, tuple):
368366
for i, arg in enumerate(record.args):
369367
attrs[f"sentry.message.parameters.{i}"] = (
370-
arg if isinstance(arg, str) else json.dumps(arg)
368+
arg if isinstance(arg, str) else safe_repr(arg)
371369
)
372370
if record.lineno:
373371
attrs["code.line.number"] = record.lineno

tests/test_logs.py

+38
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,41 @@ def test_no_log_infinite_loop(sentry_init, capture_envelopes):
281281
python_logger.debug("this is %s a template %s", "1", "2")
282282

283283
assert len(envelopes) == 1
284+
285+
286+
@minimum_python_37
287+
def test_logging_errors(sentry_init, capture_envelopes):
288+
"""
289+
The python logger module should be able to log errors without erroring
290+
"""
291+
sentry_init(_experiments={"enable_sentry_logs": True})
292+
envelopes = capture_envelopes()
293+
294+
python_logger = logging.Logger("test-logger")
295+
python_logger.error(Exception("test exc 1"))
296+
python_logger.error("error is %s", Exception("test exc 2"))
297+
298+
error_event_1 = envelopes[0].items[0].payload.json
299+
assert error_event_1["level"] == "error"
300+
301+
log_event_1 = envelopes[1].items[0].payload.json
302+
assert log_event_1["severityText"] == "error"
303+
# When only logging an exception, there is no "sentry.message.template" or "sentry.message.parameters.0"
304+
assert len(log_event_1["attributes"]) == 10
305+
assert log_event_1["attributes"][0]["key"] == "code.line.number"
306+
307+
error_event_2 = envelopes[2].items[0].payload.json
308+
assert error_event_2["level"] == "error"
309+
310+
log_event_2 = envelopes[3].items[0].payload.json
311+
assert log_event_2["severityText"] == "error"
312+
assert len(log_event_2["attributes"]) == 12
313+
assert log_event_2["attributes"][0]["key"] == "sentry.message.template"
314+
assert log_event_2["attributes"][0]["value"] == {"stringValue": "error is %s"}
315+
assert log_event_2["attributes"][1]["key"] == "sentry.message.parameters.0"
316+
assert log_event_2["attributes"][1]["value"] == {
317+
"stringValue": "Exception('test exc 2')"
318+
}
319+
assert log_event_2["attributes"][2]["key"] == "code.line.number"
320+
321+
assert len(envelopes) == 4

0 commit comments

Comments
 (0)