@@ -162,17 +162,26 @@ def get_type_module(cls):
162
162
return mod
163
163
164
164
165
+ def should_hide_frame (frame ):
166
+ try :
167
+ mod = frame .f_globals ["__name__" ]
168
+ return mod .startswith ("sentry_sdk." )
169
+ except (AttributeError , KeyError ):
170
+ pass
171
+
172
+ for flag_name in "__traceback_hide__" , "__tracebackhide__" :
173
+ try :
174
+ if frame .f_locals [flag_name ]:
175
+ return True
176
+ except Exception :
177
+ pass
178
+
179
+ return False
180
+
181
+
165
182
def iter_stacks (tb ):
166
183
while tb is not None :
167
- skip = False
168
- for flag_name in "__traceback_hide__" , "__tracebackhide__" :
169
- try :
170
- if tb .tb_frame .f_locals [flag_name ]:
171
- skip = True
172
- except Exception :
173
- pass
174
-
175
- if not skip :
184
+ if not should_hide_frame (tb .tb_frame ):
176
185
yield tb
177
186
tb = tb .tb_next
178
187
@@ -242,19 +251,6 @@ def get_source_context(frame, tb_lineno):
242
251
return [], None , []
243
252
244
253
245
- def skip_internal_frames (frame ):
246
- tb = frame
247
- while tb is not None :
248
- try :
249
- mod = tb .tb_frame .f_globals ["__name__" ]
250
- if not mod .startswith ("sentry_sdk." ):
251
- break
252
- except (AttributeError , KeyError ):
253
- pass
254
- tb = tb .tb_next
255
- return tb
256
-
257
-
258
254
def safe_str (value ):
259
255
try :
260
256
return text_type (value )
@@ -308,8 +304,7 @@ def extract_locals(frame):
308
304
return rv
309
305
310
306
311
- def frame_from_traceback (tb , with_locals = True ):
312
- frame = tb .tb_frame
307
+ def serialize_frame (frame , tb_lineno = None , with_locals = True ):
313
308
f_code = getattr (frame , "f_code" , None )
314
309
if f_code :
315
310
abs_path = frame .f_code .co_filename
@@ -322,14 +317,17 @@ def frame_from_traceback(tb, with_locals=True):
322
317
except Exception :
323
318
module = None
324
319
325
- pre_context , context_line , post_context = get_source_context (frame , tb .tb_lineno )
320
+ if tb_lineno is None :
321
+ tb_lineno = frame .f_lineno
322
+
323
+ pre_context , context_line , post_context = get_source_context (frame , tb_lineno )
326
324
327
325
rv = {
328
326
"filename" : abs_path and os .path .basename (abs_path ) or None ,
329
327
"abs_path" : os .path .abspath (abs_path ),
330
328
"function" : function or "<unknown>" ,
331
329
"module" : module ,
332
- "lineno" : tb . tb_lineno ,
330
+ "lineno" : tb_lineno ,
333
331
"pre_context" : pre_context ,
334
332
"context_line" : context_line ,
335
333
"post_context" : post_context ,
@@ -339,8 +337,30 @@ def frame_from_traceback(tb, with_locals=True):
339
337
return rv
340
338
341
339
342
- def stacktrace_from_traceback (tb , with_locals = True ):
343
- return {"frames" : [frame_from_traceback (tb , with_locals ) for tb in iter_stacks (tb )]}
340
+ def stacktrace_from_traceback (tb = None , with_locals = True ):
341
+ return {
342
+ "frames" : [
343
+ serialize_frame (
344
+ tb .tb_frame , tb_lineno = tb .tb_lineno , with_locals = with_locals
345
+ )
346
+ for tb in iter_stacks (tb )
347
+ ]
348
+ }
349
+
350
+
351
+ def current_stacktrace (with_locals = True ):
352
+ __tracebackhide__ = True
353
+ frames = []
354
+
355
+ f = sys ._getframe ()
356
+ while f is not None :
357
+ if not should_hide_frame (f ):
358
+ frames .append (serialize_frame (f , with_locals = with_locals ))
359
+ f = f .f_back
360
+
361
+ frames .reverse ()
362
+
363
+ return {"frames" : frames }
344
364
345
365
346
366
def get_errno (exc_value ):
@@ -356,23 +376,19 @@ def single_exception_from_error_tuple(
356
376
mechanism_meta = mechanism .setdefault ("meta" , {})
357
377
mechanism_meta .setdefault ("errno" , {"code" : errno })
358
378
359
- rv = {
379
+ if client_options is None :
380
+ with_locals = True
381
+ else :
382
+ with_locals = client_options ["with_locals" ]
383
+
384
+ return {
360
385
"module" : get_type_module (exc_type ),
361
386
"type" : get_type_name (exc_type ),
362
387
"value" : safe_str (exc_value ),
363
388
"mechanism" : mechanism ,
389
+ "stacktrace" : stacktrace_from_traceback (tb , with_locals ),
364
390
}
365
391
366
- if client_options is None or client_options ["attach_stacktrace" ]:
367
- if client_options is None :
368
- with_locals = True
369
- else :
370
- with_locals = client_options ["with_locals" ]
371
-
372
- rv ["stacktrace" ] = stacktrace_from_traceback (tb , with_locals )
373
-
374
- return rv
375
-
376
392
377
393
def exceptions_from_error_tuple (exc_info , client_options = None , mechanism = None ):
378
394
exc_type , exc_value , tb = exc_info
@@ -453,9 +469,6 @@ def exc_info_from_error(error):
453
469
exc_value = error
454
470
exc_type = type (error )
455
471
456
- if tb is not None :
457
- tb = skip_internal_frames (tb )
458
-
459
472
return exc_type , exc_value , tb
460
473
461
474
0 commit comments