def test_find_stacktraces_skip_none(self): # This tests: # 1. exception is None # 2. stacktrace is None # 3. frames is None # 3. frames contains only None # 4. frame is None data = { "message": "hello", "platform": "javascript", "exception": { "values": [ None, {"type": "Error", "stacktrace": None}, {"type": "Error", "stacktrace": {"frames": None}}, {"type": "Error", "stacktrace": {"frames": [None]}}, { "type": "Error", "stacktrace": { "frames": [ None, { "abs_path": "http://example.com/foo.js", "filename": "foo.js", "lineno": 4, "colno": 0, }, { "abs_path": "http://example.com/foo.js", "filename": "foo.js", "lineno": 1, "colno": 0, }, ] }, }, ] }, } infos = find_stacktraces_in_data(data, with_exceptions=True) assert len(infos) == 4 assert sum(1 for x in infos if x.stacktrace) == 3 assert sum(1 for x in infos if x.is_exception) == 4 # XXX: The null frame is still part of this stack trace! assert len(infos[3].stacktrace["frames"]) == 3 infos = find_stacktraces_in_data(data) assert len(infos) == 1 # XXX: The null frame is still part of this stack trace! assert len(infos[0].stacktrace["frames"]) == 3
def test_stacktraces_threads(self): data = { "message": "hello", "platform": "javascript", "threads": { "values": [ { "id": "4711", "stacktrace": { "frames": [ { "abs_path": "http://example.com/foo.js", "filename": "foo.js", "lineno": 4, "colno": 0, }, { "abs_path": "http://example.com/foo.js", "filename": "foo.js", "lineno": 1, "colno": 0, }, ] }, } ] }, } infos = find_stacktraces_in_data(data) assert len(infos) == 1 assert len(infos[0].stacktrace["frames"]) == 2
def test_stacktraces_basics(self): data = { "message": "hello", "platform": "javascript", "stacktrace": { "frames": [ { "abs_path": "http://example.com/foo.js", "filename": "foo.js", "lineno": 4, "colno": 0, }, { "abs_path": "http://example.com/foo.js", "filename": "foo.js", "lineno": 1, "colno": 0, "platform": "native", }, ] }, } infos = find_stacktraces_in_data(data) assert len(infos) == 1 assert len(infos[0].stacktrace["frames"]) == 2 assert infos[0].platforms == set(["javascript", "native"])
def test_stacktraces_basics(self): data = { 'message': 'hello', 'platform': 'javascript', 'stacktrace': { 'frames': [ { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 4, 'colno': 0, }, { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 1, 'colno': 0, 'platform': 'native', }, ], }, } infos = find_stacktraces_in_data(data) assert len(infos) == 1 assert len(infos[0].stacktrace['frames']) == 2 assert infos[0].platforms == set(['javascript', 'native'])
def test_stacktraces_threads(self): data = { 'message': 'hello', 'platform': 'javascript', 'threads': { 'values': [{ 'id': '4711', 'stacktrace': { 'frames': [ { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 4, 'colno': 0, }, { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 1, 'colno': 0, }, ], }, }] } } infos = find_stacktraces_in_data(data) assert len(infos) == 1 assert len(infos[0].stacktrace['frames']) == 2
def test_stacktraces_threads(self): data = { 'message': 'hello', 'platform': 'javascript', 'threads': { 'values': [ { 'id': '4711', 'stacktrace': { 'frames': [ { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 4, 'colno': 0, }, { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 1, 'colno': 0, }, ], }, } ] } } infos = find_stacktraces_in_data(data) assert len(infos) == 1 assert len(infos[0].stacktrace['frames']) == 2
def is_native_event(data): if is_native_platform(data.get("platform")): return True for stacktrace in find_stacktraces_in_data(data): if any(is_native_platform(x) for x in stacktrace.platforms): return True return False
def test_find_stacktraces_skip_none(self): # This tests: # 1. exception is None # 2. stacktrace is None # 3. frames is None # 3. frames contains only None # 4. frame is None data = { 'message': 'hello', 'platform': 'javascript', 'exception': { 'values': [ None, { 'type': 'Error', 'stacktrace': None, }, { 'type': 'Error', 'stacktrace': { 'frames': None, }, }, { 'type': 'Error', 'stacktrace': { 'frames': [None], }, }, { 'type': 'Error', 'stacktrace': { 'frames': [ None, { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 4, 'colno': 0, }, { 'abs_path': 'http://example.com/foo.js', 'filename': 'foo.js', 'lineno': 1, 'colno': 0, }, ], }, }, ] } } infos = find_stacktraces_in_data(data) assert len(infos) == 1 # XXX: The null frame is still part of this stack trace! assert len(infos[0].stacktrace['frames']) == 3
def event_supports_reprocessing(data): """Only events of a certain format support reprocessing.""" from sentry.stacktraces.processing import find_stacktraces_in_data from sentry.stacktraces.platform import NATIVE_PLATFORMS, JAVASCRIPT_PLATFORMS platform = data.get("platform") if platform in NATIVE_PLATFORMS: return True elif platform == "java" and data.get("debug_meta"): return True elif platform not in JAVASCRIPT_PLATFORMS: return False for stacktrace_info in find_stacktraces_in_data(data): if not stacktrace_info.platforms.isdisjoint(NATIVE_PLATFORMS): return True return False
def generate_modules(data): from sentry.lang.javascript.processor import generate_module for info in find_stacktraces_in_data(data): for frame in get_path(info.stacktrace, "frames", filter=True, default=()): platform = frame.get("platform") or data["platform"] if platform not in ("javascript", "node") or frame.get("module"): continue abs_path = frame.get("abs_path") if abs_path and abs_path.startswith( ("http:", "https:", "webpack:", "app:")): frame["module"] = generate_module(abs_path)
def generate_modules(data): from sentry.lang.javascript.processor import generate_module for info in find_stacktraces_in_data(data): for frame in get_path(info.stacktrace, 'frames', filter=True, default=()): platform = frame.get('platform') or data['platform'] if platform not in ('javascript', 'node') or frame.get('module'): continue abs_path = frame.get('abs_path') if abs_path and abs_path.startswith( ('http:', 'https:', 'webpack:', 'app:')): frame['module'] = generate_module(abs_path)
def process_payload(data): project = Project.objects.get_from_cache(id=data["project"]) symbolicator = Symbolicator(project=project, event_id=data["event_id"]) stacktrace_infos = [ stacktrace for stacktrace in find_stacktraces_in_data(data) if any( is_native_platform(x) for x in stacktrace.platforms) ] modules = native_images_from_data(data) stacktraces = [{ "registers": sinfo.stacktrace.get("registers") or {}, "frames": get_frames_for_symbolication( sinfo.stacktrace.get("frames") or (), data, modules), } for sinfo in stacktrace_infos] if not any(stacktrace["frames"] for stacktrace in stacktraces): return signal = signal_from_data(data) response = symbolicator.process_payload(stacktraces=stacktraces, modules=modules, signal=signal) if not _handle_response_status(data, response): return data assert len(modules) == len(response["modules"]), (modules, response) sdk_info = get_sdk_from_event(data) for raw_image, complete_image in zip(modules, response["modules"]): _merge_image(raw_image, complete_image, sdk_info, data) assert len(stacktraces) == len(response["stacktraces"]), (stacktraces, response) for sinfo, complete_stacktrace in zip(stacktrace_infos, response["stacktraces"]): complete_frames_by_idx = {} for complete_frame in complete_stacktrace.get("frames") or (): complete_frames_by_idx.setdefault(complete_frame["original_index"], []).append(complete_frame) new_frames = [] native_frames_idx = 0 for raw_frame in reversed(sinfo.stacktrace["frames"]): if not _handles_frame(data, raw_frame): new_frames.append(raw_frame) continue for complete_frame in complete_frames_by_idx.get( native_frames_idx) or (): merged_frame = dict(raw_frame) _merge_frame(merged_frame, complete_frame) if merged_frame.get("package"): raw_frame["package"] = merged_frame["package"] new_frames.append(merged_frame) native_frames_idx += 1 if sinfo.container is not None and native_frames_idx > 0: sinfo.container["raw_stacktrace"] = { "frames": list(sinfo.stacktrace["frames"]), "registers": sinfo.stacktrace.get("registers"), } new_frames.reverse() sinfo.stacktrace["frames"] = new_frames return data
def process_payload(data): project = Project.objects.get_from_cache(id=data['project']) symbolicator = Symbolicator(project=project, event_id=data['event_id']) stacktrace_infos = [ stacktrace for stacktrace in find_stacktraces_in_data(data) if any( is_native_platform(x) for x in stacktrace.platforms) ] stacktraces = [{ 'registers': sinfo.stacktrace.get('registers') or {}, 'frames': [ f for f in reversed(sinfo.stacktrace.get('frames') or ()) if _handles_frame(data, f) ] } for sinfo in stacktrace_infos] if not any(stacktrace['frames'] for stacktrace in stacktraces): return modules = native_images_from_data(data) signal = signal_from_data(data) response = symbolicator.process_payload( stacktraces=stacktraces, modules=modules, signal=signal, ) if not _handle_response_status(data, response): return data assert len(modules) == len(response['modules']), (modules, response) sdk_info = get_sdk_from_event(data) for raw_image, complete_image in zip(modules, response['modules']): _merge_image(raw_image, complete_image, sdk_info, lambda e: write_error(e, data)) assert len(stacktraces) == len(response['stacktraces']), (stacktraces, response) for sinfo, complete_stacktrace in zip(stacktrace_infos, response['stacktraces']): complete_frames_by_idx = {} for complete_frame in complete_stacktrace.get('frames') or (): complete_frames_by_idx \ .setdefault(complete_frame['original_index'], []) \ .append(complete_frame) new_frames = [] native_frames_idx = 0 for raw_frame in reversed(sinfo.stacktrace['frames']): if not _handles_frame(data, raw_frame): new_frames.append(raw_frame) continue for complete_frame in complete_frames_by_idx.get( native_frames_idx) or (): merged_frame = dict(raw_frame) _merge_frame(merged_frame, complete_frame) if merged_frame.get('package'): raw_frame['package'] = merged_frame['package'] new_frames.append(merged_frame) native_frames_idx += 1 if sinfo.container is not None and native_frames_idx > 0: sinfo.container['raw_stacktrace'] = { 'frames': list(sinfo.stacktrace['frames']), 'registers': sinfo.stacktrace.get('registers') } new_frames.reverse() sinfo.stacktrace['frames'] = new_frames return data