def test_merge_unreal_context_event(self): with open(get_unreal_crash_file(), "rb") as f: event = {"event_id": MOCK_EVENT_ID, "environment": "Production"} user_id = "ebff51ef3c4878627823eebd9ff40eb4|2e7d369327054a448be6c8d3601213cb|C52DC39D-DAF3-5E36-A8D3-BF5F53A5D38F" merge_unreal_user(event, user_id) unreal_crash = Unreal4Crash.from_bytes(f.read()) merge_unreal_context_event(unreal_crash.get_context(), event, self.project) self.insta_snapshot(event)
def test_merge_unreal_logs_event(self): with open(get_unreal_crash_file(), "rb") as f: event = {"event_id": MOCK_EVENT_ID, "environment": None} unreal_crash = Unreal4Crash.from_bytes(f.read()) merge_unreal_logs_event(unreal_crash.get_logs(), event) breadcrumbs = event["breadcrumbs"]["values"] assert len(breadcrumbs) == 100 assert breadcrumbs[0]["timestamp"] == "2018-11-20T11:47:14Z" assert breadcrumbs[0]["message"] == " 4. 'Parallels Display Adapter (WDDM)' (P:0 D:0)" assert breadcrumbs[0]["category"] == "LogWindows" assert breadcrumbs[99]["timestamp"] == "2018-11-20T11:47:15Z" assert breadcrumbs[99]["message"] == "Texture pool size now 1000 MB" assert breadcrumbs[99]["category"] == "LogContentStreaming"
def process_unreal_crash(payload, user_id, environment, event): """Initial processing of the event from the Unreal Crash Reporter data. Processes the raw bytes of the unreal crash by returning a Unreal4Crash""" event["environment"] = environment if user_id: # https://github.com/EpicGames/UnrealEngine/blob/f509bb2d6c62806882d9a10476f3654cf1ee0634/Engine/Source/Programs/CrashReportClient/Private/CrashUpload.cpp#L769 parts = user_id.split("|", 2) login_id, epic_account_id, machine_id = parts + [""] * (3 - len(parts)) event["user"] = {"id": login_id if login_id else user_id} if epic_account_id: set_path(event, "tags", "epic_account_id", value=epic_account_id) if machine_id: set_path(event, "tags", "machine_id", value=machine_id) return Unreal4Crash.from_bytes(payload)
def post(self, request, project, project_config, **kwargs): attachments_enabled = features.has( "organizations:event-attachments", project.organization, actor=request.user ) attachments = [] event = {"event_id": uuid.uuid4().hex, "environment": request.GET.get("AppEnvironment")} user_id = request.GET.get("UserID") if user_id: merge_unreal_user(event, user_id) try: unreal = Unreal4Crash.from_bytes(request.body) except (ProcessMinidumpError, Unreal4Error) as e: minidumps_logger.exception(e) track_outcome( project_config.organization_id, project_config.project_id, None, Outcome.INVALID, "process_unreal", ) raise APIError(e.message.split("\n", 1)[0]) try: unreal_context = unreal.get_context() except Unreal4Error as e: # we'll continue without the context data unreal_context = None minidumps_logger.exception(e) else: if unreal_context is not None: merge_unreal_context_event(unreal_context, event, project) try: unreal_logs = unreal.get_logs() except Unreal4Error as e: # we'll continue without the breadcrumbs minidumps_logger.exception(e) else: if unreal_logs is not None: merge_unreal_logs_event(unreal_logs, event) is_minidump = False is_applecrashreport = False for file in unreal.files(): # Known attachment: msgpack event if file.name == "__sentry-event": merge_attached_event(file.open_stream(), event) continue if file.name in ("__sentry-breadcrumb1", "__sentry-breadcrumb2"): merge_attached_breadcrumbs(file.open_stream(), event) continue if file.type == "minidump": is_minidump = True if file.type == "applecrashreport": is_applecrashreport = True # Always store attachments that can be processed, regardless of the # event-attachments feature. if file.type in self.required_attachments or attachments_enabled: attachments.append( CachedAttachment( name=file.name, data=file.open_stream().read(), type=unreal_attachment_type(file), ) ) if is_minidump: write_minidump_placeholder(event) elif is_applecrashreport: write_applecrashreport_placeholder(event) event_id = self.process( request, attachments=attachments, data=event, project=project, project_config=project_config, **kwargs ) # The return here is only useful for consistency # because the UE4 crash reporter doesn't care about it. return HttpResponse(six.text_type(uuid.UUID(event_id)), content_type="text/plain")
def process_unreal_crash(data): """Processes the raw bytes of the unreal crash""" return Unreal4Crash.from_bytes(data)