55import pytest
66from logging import getLogger
77from sentry_sdk .tracing import Transaction
8+ from fastapi_jsonrpc import BaseError
9+
810from fastapi_jsonrpc .contrib .sentry .test_utils import (
911 get_transaction_trace_id ,
1012 get_captured_transactions ,
1618 pytest .skip (f"Testset is only for sentry_sdk 2.x, given { sentry_sdk_version = } " , allow_module_level = True )
1719
1820
21+ class JrpcSampleError (BaseError ):
22+ CODE = 5001
23+ MESSAGE = "Sample JRPC error"
24+
25+
1926@pytest .fixture
2027def failing_router (ep ):
2128 sub_app = ep
2229 logger = getLogger ("test-sentry" )
2330
24- @sub_app .method (name = "first_failing_method " )
25- async def first_failing_method () :
31+ @sub_app .method (name = "first_logged_error_method " )
32+ async def first_logged_error_method () -> dict :
2633 try :
2734 raise ValueError ()
2835 except Exception :
29- logger .exception ("First route exc" )
36+ logger .exception ("First logged error method exc" )
37+
38+ return {"handled" : True }
3039
31- @sub_app .method (name = "second_failing_method " )
32- async def second_failing_method () :
40+ @sub_app .method (name = "second_logged_error_method " )
41+ async def second_logged_error_method () -> dict :
3342 try :
3443 raise TypeError ()
3544 except Exception :
36- logger .exception ("Second route exc" )
45+ logger .exception ("Second logged error method exc" )
3746
38- @sub_app .method (name = "unhandled_error_method" )
39- async def unhandled_error_method ():
40- raise RuntimeError ("Third route exc" )
47+ return {"handled" : True }
4148
42- @sub_app .method (name = "successful_method " )
43- async def successful_method () :
44- pass
49+ @sub_app .method (name = "unhandled_error_method " )
50+ async def unhandled_error_method () -> dict :
51+ raise RuntimeError ( "Unhandled method exc" )
4552
53+ @sub_app .method (name = "jrpc_error_method" )
54+ async def jrpc_error_method () -> dict :
55+ raise JrpcSampleError ()
4656
47- def test_exception_logger_event_creation (
48- json_request , capture_exceptions , capture_events , capture_envelopes , failing_router , sentry_with_integration ,
49- assert_log_errors ,
57+ @sub_app .method (name = "successful_method" )
58+ async def successful_method () -> dict :
59+ return {"success" : True }
60+
61+
62+ def test_logged_exceptions_event_creation (
63+ json_request ,
64+ capture_exceptions ,
65+ capture_events ,
66+ capture_envelopes ,
67+ failing_router ,
68+ sentry_with_integration ,
69+ assert_log_errors ,
5070):
5171 exceptions = capture_exceptions ()
5272 envelops = capture_envelopes ()
53- json_request (
73+ response = json_request (
5474 [
55- {"jsonrpc" : "2.0" , "method" : "first_failing_method" , "params" : {}, "id" : 1 },
56- {"jsonrpc" : "2.0" , "method" : "second_failing_method" , "params" : {}, "id" : 1 },
75+ {
76+ "method" : "first_logged_error_method" ,
77+ "params" : {},
78+ "jsonrpc" : "2.0" ,
79+ "id" : 1 ,
80+ },
81+ {
82+ "method" : "second_logged_error_method" ,
83+ "params" : {},
84+ "jsonrpc" : "2.0" ,
85+ "id" : 1 ,
86+ },
5787 ],
5888 )
89+ assert response == [
90+ {
91+ "result" : {"handled" : True },
92+ "jsonrpc" : "2.0" ,
93+ "id" : 1 ,
94+ },
95+ {
96+ "result" : {"handled" : True },
97+ "jsonrpc" : "2.0" ,
98+ "id" : 1 ,
99+ },
100+ ]
59101 assert {type (e ) for e in exceptions } == {ValueError , TypeError }
60102 assert_log_errors (
61- 'First route exc' , pytest .raises (ValueError ),
62- 'Second route exc' , pytest .raises (TypeError ),
103+ "First logged error method exc" ,
104+ pytest .raises (ValueError ),
105+ "Second logged error method exc" ,
106+ pytest .raises (TypeError ),
63107 )
64108 # 2 errors and 2 transactions
65109 assert_jrpc_batch_sentry_items (envelops , expected_items = {"event" : 2 , "transaction" : 2 })
66110
67111
68- def test_unhandled_exception_capturing (
69- json_request , capture_exceptions , capture_events , capture_envelopes , failing_router , assert_log_errors ,
70- sentry_with_integration
112+ def test_unhandled_exception_event_creation (
113+ json_request ,
114+ capture_exceptions ,
115+ capture_events ,
116+ capture_envelopes ,
117+ failing_router ,
118+ assert_log_errors ,
119+ sentry_with_integration ,
71120):
72121 exceptions = capture_exceptions ()
73122 envelops = capture_envelopes ()
74- json_request ({"jsonrpc" : "2.0" , "method" : "unhandled_error_method" , "params" : {}, "id" : 1 })
123+ response = json_request (
124+ {
125+ "method" : "unhandled_error_method" ,
126+ "params" : {},
127+ "jsonrpc" : "2.0" ,
128+ "id" : 1 ,
129+ }
130+ )
131+ assert response == {
132+ "error" : {"code" : - 32603 , "message" : "Internal error" },
133+ "jsonrpc" : "2.0" ,
134+ "id" : 1 ,
135+ }
75136 assert_log_errors (
76- "Third route exc" ,
137+ "Unhandled method exc" ,
77138 pytest .raises (RuntimeError ),
78139 )
79140 assert {type (e ) for e in exceptions } == {RuntimeError }
@@ -86,50 +147,65 @@ def test_unhandled_exception_capturing(
86147 [
87148 [
88149 {
89- "jsonrpc" : "2.0" ,
90- "method" : "first_failing_method" ,
150+ "method" : "jrpc_error_method" ,
91151 "params" : {},
152+ "jsonrpc" : "2.0" ,
92153 "id" : 1 ,
93154 },
94155 {
95- "jsonrpc" : "2.0" ,
96156 "method" : "unhandled_error_method" ,
97157 "params" : {},
158+ "jsonrpc" : "2.0" ,
98159 "id" : 1 ,
99160 },
100161 {
101- "jsonrpc" : "2.0" ,
102162 "method" : "successful_method" ,
103163 "params" : {},
164+ "jsonrpc" : "2.0" ,
104165 "id" : 1 ,
105166 },
106167 ]
107168 ],
108169)
109170def test_trace_id_propagation (
110- request_payload , json_request , capture_exceptions , capture_events , capture_envelopes , failing_router ,
111- assert_log_errors , sentry_with_integration
171+ request_payload ,
172+ json_request ,
173+ capture_exceptions ,
174+ capture_events ,
175+ capture_envelopes ,
176+ failing_router ,
177+ assert_log_errors ,
178+ sentry_with_integration ,
112179):
113180 envelops = capture_envelopes ()
114181 expected_trace_id = uuid .uuid4 ().hex
115182 incoming_transaction = Transaction (trace_id = expected_trace_id )
116183 tracing_headers = list (incoming_transaction .iter_headers ())
117- json_request (
118- request_payload ,
119- headers = tracing_headers ,
120- )
121- assert_jrpc_batch_sentry_items (envelops , expected_items = {"transaction" : 3 , "event" : 2 })
184+
185+ response = json_request (request_payload , headers = tracing_headers )
186+
187+ assert response == [
188+ {
189+ "error" : {"code" : 5001 , "message" : "Sample JRPC error" },
190+ "jsonrpc" : "2.0" ,
191+ "id" : 1 ,
192+ },
193+ {
194+ "error" : {"code" : - 32603 , "message" : "Internal error" },
195+ "jsonrpc" : "2.0" ,
196+ "id" : 1 ,
197+ },
198+ {
199+ "result" : {"success" : True },
200+ "jsonrpc" : "2.0" ,
201+ "id" : 1 ,
202+ },
203+ ]
204+ assert_jrpc_batch_sentry_items (envelops , expected_items = {"transaction" : 3 , "event" : 1 })
122205 for transaction in get_captured_transactions (envelops ):
123206 assert get_transaction_trace_id (transaction ) == expected_trace_id
124207
125208 assert_log_errors (
126- 'First route exc' , pytest . raises ( ValueError ) ,
127- 'Third route exc' , pytest .raises (RuntimeError ),
209+ "Unhandled method exc" ,
210+ pytest .raises (RuntimeError ),
128211 )
129-
130-
131- def test_no_integration_warning_message (json_request , sentry_no_integration ):
132- with pytest .warns (UserWarning , match = "Implicit Sentry integration is deprecated" ):
133- json_request (
134- {"jsonrpc" : "2.0" , "method" : "successful_method" , "params" : {}, "id" : 1 }
135- )
0 commit comments