1+ import copy
12import logging
23import typing
34
45import pytest
56import sentry_sdk
7+ import structlog
8+ from sentry_sdk .integrations .logging import LoggingIntegration
69
7- from tests .conftest import SentryTestTransport
10+ from lite_bootstrap .instruments .logging_instrument import LoggingConfig , LoggingInstrument
11+ from tests .conftest import LoggingMock , SentryTestTransport
812
913
1014if typing .TYPE_CHECKING :
11- pass
15+ from sentry_sdk import _types as sentry_types
1216
1317from lite_bootstrap .instruments .sentry_instrument import (
1418 SentryConfig ,
1519 SentryInstrument ,
20+ enrich_sentry_event_from_structlog_log ,
1621)
1722
1823
19- logger = logging .getLogger (__name__ )
24+ std_logger = logging .getLogger (__name__ )
25+ logger = structlog .getLogger (__name__ )
2026
2127
2228@pytest .fixture
@@ -31,12 +37,80 @@ def minimal_sentry_config(sentry_mock: SentryTestTransport) -> SentryConfig:
3137def test_sentry_instrument_with_raise (minimal_sentry_config : SentryConfig , sentry_mock : SentryTestTransport ) -> None :
3238 SentryInstrument (bootstrap_config = minimal_sentry_config ).bootstrap ()
3339
40+ try :
41+ std_logger .error ("some error" )
42+ assert len (sentry_mock .mock_envelopes ) == 1
43+ finally :
44+ sentry_sdk .init ()
45+
46+
47+ def test_sentry_instrument_with_structlog_error (
48+ minimal_sentry_config : SentryConfig , sentry_mock : SentryTestTransport , logging_mock : LoggingMock
49+ ) -> None :
50+ SentryInstrument (bootstrap_config = minimal_sentry_config ).bootstrap ()
51+ logging_instrument = LoggingInstrument (
52+ bootstrap_config = LoggingConfig (
53+ logging_unset_handlers = ["uvicorn" ],
54+ logging_buffer_capacity = 0 ,
55+ service_debug = False ,
56+ logging_extra_processors = [logging_mock ],
57+ )
58+ )
59+ logging_instrument .bootstrap ()
60+
3461 try :
3562 logger .error ("some error" )
63+ logger .error ("some error, skipping sentry" , skip_sentry = True )
3664 assert len (sentry_mock .mock_envelopes ) == 1
65+ LoggingIntegration ()
3766 finally :
3867 sentry_sdk .init ()
68+ logging_instrument .teardown ()
3969
4070
4171def test_sentry_instrument_empty_dsn () -> None :
4272 SentryInstrument (bootstrap_config = SentryConfig (sentry_dsn = "" )).bootstrap ()
73+
74+
75+ class TestSentryEnrichEventFromStructlog :
76+ @pytest .mark .parametrize (
77+ "event" ,
78+ [
79+ {},
80+ {"logentry" : None },
81+ {"logentry" : {}},
82+ {"logentry" : {"formatted" : b"" }},
83+ {"logentry" : {"formatted" : "" }},
84+ {"logentry" : {"formatted" : "hi" }},
85+ {"logentry" : {"formatted" : "[]" }},
86+ {"logentry" : {"formatted" : "[{}]" }},
87+ {"logentry" : {"formatted" : "{" }, "contexts" : {}},
88+ {"logentry" : {"formatted" : "{}" }, "contexts" : {}},
89+ ],
90+ )
91+ def test_skip (self , event : "sentry_types.Event" ) -> None :
92+ assert enrich_sentry_event_from_structlog_log (copy .deepcopy (event ), {}) == event
93+
94+ @pytest .mark .parametrize (
95+ ("event_before" , "event_after" ),
96+ [
97+ (
98+ {"logentry" : {"formatted" : '{"event": "event name"}' }, "contexts" : {}},
99+ {"logentry" : {"formatted" : "event name" }, "contexts" : {}},
100+ ),
101+ (
102+ {
103+ "logentry" : {
104+ "formatted" : '{"event": "event name", "timestamp": 1, "level": "error", "logger": "event.logger", "tracing": {}, "foo": "bar"}' # noqa: E501
105+ },
106+ "contexts" : {},
107+ },
108+ {
109+ "logentry" : {"formatted" : "event name" },
110+ "contexts" : {"structlog" : {"foo" : "bar" }},
111+ },
112+ ),
113+ ],
114+ )
115+ def test_modify (self , event_before : "sentry_types.Event" , event_after : "sentry_types.Event" ) -> None :
116+ assert enrich_sentry_event_from_structlog_log (event_before , {}) == event_after
0 commit comments