@@ -73,6 +73,16 @@ def get_excepthook_client():
73
73
return client
74
74
75
75
76
+ def get_loop_excepthook_client (loop = None ):
77
+ import asyncio
78
+
79
+ loop = loop or asyncio .get_event_loop ()
80
+ hook = loop .get_exception_handler ()
81
+ client = getattr (hook , 'raven_client' , None )
82
+ if client is not None :
83
+ return client
84
+
85
+
76
86
class ModuleProxyCache (dict ):
77
87
def __missing__ (self , key ):
78
88
module , class_name = key .rsplit ('.' , 1 )
@@ -283,6 +293,58 @@ def install_logging_hook(self):
283
293
from raven .breadcrumbs import install_logging_hook
284
294
install_logging_hook ()
285
295
296
+ def install_asyncio_hook (self , loop = None ):
297
+ import asyncio
298
+
299
+ loop = loop or asyncio .get_event_loop ()
300
+
301
+ try :
302
+ loop_except_handler = loop .get_exception_handler ()
303
+ except AttributeError :
304
+ # No get_exception_handler before Python 3.5.2
305
+ loop_except_handler = getattr (loop , '_exception_handler' , None )
306
+
307
+ if not loop_except_handler :
308
+ loop_except_handler = type (loop ).default_exception_handler
309
+
310
+ def handle_exception (loop , context ):
311
+ if 'exception' in context :
312
+ exception = context ['exception' ]
313
+ exc_info = type (exception ), exception , exception .__traceback__
314
+ self .captureException (exc_info = exc_info , level = 'exception' ) # asyncio exceptions are non-fatal
315
+ else :
316
+ data = {}
317
+
318
+ if 'source_traceback' in context :
319
+ tb = context ['source_traceback' ]
320
+ elif 'handle' in context and getattr (context ['handle' ], '_source_traceback' , None ):
321
+ tb = context ['handle' ]._source_traceback
322
+ elif 'future' in context and getattr (context ['future' ], '_source_traceback' , None ):
323
+ tb = context ['future' ]._source_traceback
324
+ else :
325
+ tb = None
326
+
327
+ if tb :
328
+ frames = []
329
+
330
+ for file_name , lineno , function_name , text in tb :
331
+ frames .append ({
332
+ 'filename' : file_name ,
333
+ 'lineno' : lineno ,
334
+ 'function' : function_name ,
335
+ })
336
+
337
+ if frames :
338
+ data = {'stacktrace' : {'frames' : frames }}
339
+
340
+ message = context .get ('message' , 'Unhandled exception in event loop' )
341
+ self .captureMessage (message , data = data , level = 'exception' )
342
+
343
+ loop_except_handler (loop , context )
344
+
345
+ handle_exception .raven_client = self
346
+ loop .set_exception_handler (handle_exception )
347
+
286
348
def hook_libraries (self , libraries ):
287
349
from raven .breadcrumbs import hook_libraries
288
350
hook_libraries (libraries )
0 commit comments