Skip to content

Commit a67cddb

Browse files
committed
feat: logging now uses breadcrumbs like rust sdk
1 parent 09fe647 commit a67cddb

File tree

4 files changed

+36
-10
lines changed

4 files changed

+36
-10
lines changed

sentry_sdk/hub.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,9 @@ def add_breadcrumb(self, crumb):
152152
if callable(crumb):
153153
crumb = crumb()
154154
if crumb is not None:
155-
scope.breadcrumbs.append(crumb)
156-
while len(scope.breadcrumbs) >= client.options['max_breadcrumbs']:
157-
scope.breadcrumbs.popleft()
155+
scope._breadcrumbs.append(crumb)
156+
while len(scope._breadcrumbs) >= client.options['max_breadcrumbs']:
157+
scope._breadcrumbs.popleft()
158158

159159
def add_event_processor(self, factory):
160160
"""Registers a new event processor with the top scope."""

sentry_sdk/integrations/logging.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import logging
55

6-
from sentry_sdk import get_current_hub, capture_event
6+
from sentry_sdk import get_current_hub, capture_event, add_breadcrumb
77
from sentry_sdk.utils import to_string, create_event, exceptions_from_error_tuple, skip_internal_frames
88

99
class SentryHandler(logging.Handler, object):
@@ -17,7 +17,20 @@ def emit(self, record):
1717
def can_record(self, record):
1818
return not record.name.startswith('sentry_sdk')
1919

20+
def _breadcrumb_from_record(self, record):
21+
return {
22+
'ty': 'log',
23+
'level': self._logging_to_event_level(record.levelname),
24+
'category': record.name,
25+
'message': record.message
26+
}
27+
2028
def _emit(self, record):
29+
add_breadcrumb(self._breadcrumb_from_record(record))
30+
31+
if not self._should_create_event(record):
32+
return
33+
2134
if not self.can_record(record):
2235
print(to_string(record.message), file=sys.stderr)
2336
return
@@ -32,7 +45,7 @@ def _emit(self, record):
3245
get_current_hub().client.options['with_locals']
3346
)
3447

35-
event['level'] = record.levelname.lower()
48+
event['level'] = self._logging_to_event_level(record.levelname)
3649
event['logger'] = record.name
3750

3851
event['logentry'] = {
@@ -42,5 +55,16 @@ def _emit(self, record):
4255

4356
capture_event(event)
4457

58+
def _logging_to_event_level(self, levelname):
59+
return {
60+
'critical': 'fatal'
61+
}.get(levelname.lower(), levelname.lower())
62+
63+
def _should_create_event(self, record):
64+
# TODO: make configurable
65+
if record.levelno in (logging.ERROR, logging.CRITICAL):
66+
return True
67+
return False
68+
4569

4670
HANDLER = SentryHandler()

tests/integrations/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import pytest
22
import sentry_sdk
3+
from sentry_sdk.consts import DEFAULT_OPTIONS
34
from sentry_sdk.client import Client, Transport
45

56
class TestClient(Client):
67
def __init__(self):
78
pass
89

910
dsn = 'LOL'
10-
options = {'with_locals': False, 'release': 'fake_release', 'environment': 'fake_environment', 'server_name': 'fake_servername'}
11+
options = dict(DEFAULT_OPTIONS)
1112
_transport = None
1213

1314

tests/integrations/logging/test_logging.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
logger.handlers = [HANDLER]
99
logger.setLevel(logging.DEBUG)
1010

11-
@pytest.mark.parametrize('level', ['info', 'debug', 'warning', 'error'])
12-
def test_logging(capture_events, level):
13-
getattr(logger, level)('LOL')
11+
def test_logging(capture_events):
12+
logger.info('bread')
13+
logger.critical('LOL')
1414
event, = capture_events
15-
assert event['level'] == level
15+
assert event['level'] == 'fatal'
1616
assert not event['logentry']['params']
1717
assert event['logentry']['message'] == 'LOL'
18+
assert event['breadcrumbs'][0]['message'] == 'bread'

0 commit comments

Comments
 (0)