Skip to content

Commit 11abdd2

Browse files
authored
Handle loguru msg levels that are not supported by Sentry (#4147)
Loguru has two message levels `TRACE` and `SUCCESS` that are not available in Sentry breadcrumbs. This PR maps `TRACE` to `debug` and `SUCCESS` to `info` in Sentry so those breadcrumbs do not show a confusing error message in the Sentry UI. Fixes #2759
1 parent bc54a1d commit 11abdd2

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

Diff for: sentry_sdk/integrations/loguru.py

+33-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
if TYPE_CHECKING:
1313
from logging import LogRecord
14-
from typing import Optional, Tuple
14+
from typing import Optional, Tuple, Any
1515

1616
try:
1717
import loguru
@@ -31,6 +31,16 @@ class LoggingLevels(enum.IntEnum):
3131
CRITICAL = 50
3232

3333

34+
SENTRY_LEVEL_FROM_LOGURU_LEVEL = {
35+
"TRACE": "DEBUG",
36+
"DEBUG": "DEBUG",
37+
"INFO": "INFO",
38+
"SUCCESS": "INFO",
39+
"WARNING": "WARNING",
40+
"ERROR": "ERROR",
41+
"CRITICAL": "CRITICAL",
42+
}
43+
3444
DEFAULT_LEVEL = LoggingLevels.INFO.value
3545
DEFAULT_EVENT_LEVEL = LoggingLevels.ERROR.value
3646
# We need to save the handlers to be able to remove them later
@@ -87,14 +97,34 @@ class _LoguruBaseHandler(_BaseHandler):
8797
def _logging_to_event_level(self, record):
8898
# type: (LogRecord) -> str
8999
try:
90-
return LoggingLevels(record.levelno).name.lower()
91-
except ValueError:
100+
return SENTRY_LEVEL_FROM_LOGURU_LEVEL[
101+
LoggingLevels(record.levelno).name
102+
].lower()
103+
except (ValueError, KeyError):
92104
return record.levelname.lower() if record.levelname else ""
93105

94106

95107
class LoguruEventHandler(_LoguruBaseHandler, EventHandler):
96108
"""Modified version of :class:`sentry_sdk.integrations.logging.EventHandler` to use loguru's level names."""
97109

110+
def __init__(self, *args, **kwargs):
111+
# type: (*Any, **Any) -> None
112+
if kwargs.get("level"):
113+
kwargs["level"] = SENTRY_LEVEL_FROM_LOGURU_LEVEL.get(
114+
kwargs.get("level", ""), DEFAULT_LEVEL
115+
)
116+
117+
super().__init__(*args, **kwargs)
118+
98119

99120
class LoguruBreadcrumbHandler(_LoguruBaseHandler, BreadcrumbHandler):
100121
"""Modified version of :class:`sentry_sdk.integrations.logging.BreadcrumbHandler` to use loguru's level names."""
122+
123+
def __init__(self, *args, **kwargs):
124+
# type: (*Any, **Any) -> None
125+
if kwargs.get("level"):
126+
kwargs["level"] = SENTRY_LEVEL_FROM_LOGURU_LEVEL.get(
127+
kwargs.get("level", ""), DEFAULT_LEVEL
128+
)
129+
130+
super().__init__(*args, **kwargs)

Diff for: tests/integrations/loguru/test_loguru.py

+12-11
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@
88

99

1010
@pytest.mark.parametrize(
11-
"level,created_event",
11+
"level,created_event,expected_sentry_level",
1212
[
1313
# None - no breadcrumb
1414
# False - no event
1515
# True - event created
16-
(LoggingLevels.TRACE, None),
17-
(LoggingLevels.DEBUG, None),
18-
(LoggingLevels.INFO, False),
19-
(LoggingLevels.SUCCESS, False),
20-
(LoggingLevels.WARNING, False),
21-
(LoggingLevels.ERROR, True),
22-
(LoggingLevels.CRITICAL, True),
16+
(LoggingLevels.TRACE, None, "debug"),
17+
(LoggingLevels.DEBUG, None, "debug"),
18+
(LoggingLevels.INFO, False, "info"),
19+
(LoggingLevels.SUCCESS, False, "info"),
20+
(LoggingLevels.WARNING, False, "warning"),
21+
(LoggingLevels.ERROR, True, "error"),
22+
(LoggingLevels.CRITICAL, True, "critical"),
2323
],
2424
)
2525
@pytest.mark.parametrize("disable_breadcrumbs", [True, False])
@@ -29,6 +29,7 @@ def test_just_log(
2929
capture_events,
3030
level,
3131
created_event,
32+
expected_sentry_level,
3233
disable_breadcrumbs,
3334
disable_events,
3435
):
@@ -48,7 +49,7 @@ def test_just_log(
4849
formatted_message = (
4950
" | "
5051
+ "{:9}".format(level.name.upper())
51-
+ "| tests.integrations.loguru.test_loguru:test_just_log:46 - test"
52+
+ "| tests.integrations.loguru.test_loguru:test_just_log:47 - test"
5253
)
5354

5455
if not created_event:
@@ -59,7 +60,7 @@ def test_just_log(
5960
not disable_breadcrumbs and created_event is not None
6061
): # not None == not TRACE or DEBUG level
6162
(breadcrumb,) = breadcrumbs
62-
assert breadcrumb["level"] == level.name.lower()
63+
assert breadcrumb["level"] == expected_sentry_level
6364
assert breadcrumb["category"] == "tests.integrations.loguru.test_loguru"
6465
assert breadcrumb["message"][23:] == formatted_message
6566
else:
@@ -72,7 +73,7 @@ def test_just_log(
7273
return
7374

7475
(event,) = events
75-
assert event["level"] == (level.name.lower())
76+
assert event["level"] == expected_sentry_level
7677
assert event["logger"] == "tests.integrations.loguru.test_loguru"
7778
assert event["logentry"]["message"][23:] == formatted_message
7879

0 commit comments

Comments
 (0)