Log Sentry crash events through MXLog

Mirror crashes into our own logs via Sentry's beforeSend hook so the full crash
log ships with rageshakes. Adds a SentryEvent extension to extract the formatted
crash log from the event.
This commit is contained in:
Stefan Ceriu
2026-06-15 14:30:18 +03:00
parent 434b3aab83
commit 0ce7a5ea13
3 changed files with 46 additions and 0 deletions
+4
View File
@@ -649,6 +649,7 @@
6B3AB95A6993646A5081BFF9 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43F773904F87FF5ADFE4DD1 /* TestablePreview.swift */; }; 6B3AB95A6993646A5081BFF9 /* TestablePreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43F773904F87FF5ADFE4DD1 /* TestablePreview.swift */; };
6B61F5B27412ED4BC2F9769C /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */; }; 6B61F5B27412ED4BC2F9769C /* test_audio.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 66B96842BF5F8ACA1AC84C55 /* test_audio.mp3 */; };
6B80C24A52411EAF10E06E96 /* SecurityAndPrivacyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBADF8010C813D905C172CE /* SecurityAndPrivacyScreenModels.swift */; }; 6B80C24A52411EAF10E06E96 /* SecurityAndPrivacyScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBADF8010C813D905C172CE /* SecurityAndPrivacyScreenModels.swift */; };
6BA9214F31A24C7A84287A56 /* SentryEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 337AD37403015231CAE3E80B /* SentryEvent.swift */; };
6BAE34CFA9821709CFE61E50 /* DeveloperOptionsScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F60FDB3AEFC60830BD289FE /* DeveloperOptionsScreenHook.swift */; }; 6BAE34CFA9821709CFE61E50 /* DeveloperOptionsScreenHook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F60FDB3AEFC60830BD289FE /* DeveloperOptionsScreenHook.swift */; };
6BEB10499149444909EBE42F /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */; }; 6BEB10499149444909EBE42F /* TrackedUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10D751743B20B314D84D79FE /* TrackedUserDefaults.swift */; };
6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; }; 6C34237AFB808E38FC8776B9 /* RoomStateEventStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D55702474F279D910D2D162 /* RoomStateEventStringBuilder.swift */; };
@@ -1942,6 +1943,7 @@
330AF4D121C3396F7A14B21D /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/SAS.strings; sourceTree = "<group>"; }; 330AF4D121C3396F7A14B21D /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/SAS.strings; sourceTree = "<group>"; };
3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVMetadataMachineReadableCodeObject.swift; sourceTree = "<group>"; }; 3339B1DDB1341E833D2555BC /* AVMetadataMachineReadableCodeObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AVMetadataMachineReadableCodeObject.swift; sourceTree = "<group>"; };
33752AE856E93CE62412B7A1 /* LiveLocationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveLocationManagerProtocol.swift; sourceTree = "<group>"; }; 33752AE856E93CE62412B7A1 /* LiveLocationManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveLocationManagerProtocol.swift; sourceTree = "<group>"; };
337AD37403015231CAE3E80B /* SentryEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEvent.swift; sourceTree = "<group>"; };
33AE897D86784CCA5E4E9227 /* ElementCallService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallService.swift; sourceTree = "<group>"; }; 33AE897D86784CCA5E4E9227 /* ElementCallService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ElementCallService.swift; sourceTree = "<group>"; };
33E49C5C6F802B4D94CA78D1 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; }; 33E49C5C6F802B4D94CA78D1 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
3423C39324CF851A72EC9976 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/SAS.strings; sourceTree = "<group>"; }; 3423C39324CF851A72EC9976 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/SAS.strings; sourceTree = "<group>"; };
@@ -4296,6 +4298,7 @@
7310D8DFE01AF45F0689C3AA /* Publisher.swift */, 7310D8DFE01AF45F0689C3AA /* Publisher.swift */,
DADECBBB672497BCD4822468 /* Result.swift */, DADECBBB672497BCD4822468 /* Result.swift */,
584A61D9C459FAFEF038A7C0 /* Section.swift */, 584A61D9C459FAFEF038A7C0 /* Section.swift */,
337AD37403015231CAE3E80B /* SentryEvent.swift */,
DF17EA323AD0205A6AB621AA /* Snapshotting.swift */, DF17EA323AD0205A6AB621AA /* Snapshotting.swift */,
40B21E611DADDEF00307E7AC /* String.swift */, 40B21E611DADDEF00307E7AC /* String.swift */,
A40C19719687984FD9478FBE /* Task.swift */, A40C19719687984FD9478FBE /* Task.swift */,
@@ -8942,6 +8945,7 @@
7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */, 7C545FFEC9930F7247352593 /* SecurityAndPrivacyScreenViewModel.swift in Sources */,
0D617A152D099D94271D3BA8 /* SecurityAndPrivacyScreenViewModelProtocol.swift in Sources */, 0D617A152D099D94271D3BA8 /* SecurityAndPrivacyScreenViewModelProtocol.swift in Sources */,
A588572ED0EB18D947B32A5E /* SendInviteConfirmationView.swift in Sources */, A588572ED0EB18D947B32A5E /* SendInviteConfirmationView.swift in Sources */,
6BA9214F31A24C7A84287A56 /* SentryEvent.swift in Sources */,
08547E55DD3686A84550996D /* SeparatorMediaEventsTimelineView.swift in Sources */, 08547E55DD3686A84550996D /* SeparatorMediaEventsTimelineView.swift in Sources */,
14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */, 14E99D27628B1A6F0CB46FEA /* SeparatorRoomTimelineItem.swift in Sources */,
5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */, 5341D48F833E3E30F16FA2A3 /* SeparatorRoomTimelineView.swift in Sources */,
@@ -1019,6 +1019,14 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
bugReportService.lastCrashEventID = event.eventId.sentryIdString bugReportService.lastCrashEventID = event.eventId.sentryIdString
} }
// Mirror every crash into our own logs (which ship with rageshakes) before it's sent to Sentry.
options.beforeSend = { event in
if let crashLog = event.crashLog {
MXLog.error("Sentry crash event \(event.eventId.sentryIdString):\n\(crashLog)")
}
return event
}
// Any ongoing transactions will no longer be valid after calling SentrySDK.start so lets // Any ongoing transactions will no longer be valid after calling SentrySDK.start so lets
// remove them and start over, otherwise the app will crash if finishTransaction is used. // remove them and start over, otherwise the app will crash if finishTransaction is used.
analytics.signpost.resetTransactions() analytics.signpost.resetTransactions()
@@ -0,0 +1,34 @@
//
// Copyright 2025 Element Creations Ltd.
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import MatrixRustSDK
import Sentry
import UIKit
extension Event {
/// A human readable crash log matching the format used by the legacy app.
/// `nil` for non-crash events (handled errors, transactions, etc.).
var crashLog: String? {
guard let exceptions,
exceptions.contains(where: { $0.mechanism?.handled?.boolValue == false }) else {
return nil
}
let reason = exceptions.map { "\($0.type ?? "Unknown"): \($0.value ?? "")" }.joined(separator: "\n")
let infoPlist = InfoPlistReader.main
let device = UIDevice.current
return """
\(reason)
Application: \(infoPlist.bundleExecutable) (\(infoPlist.bundleIdentifier))
Application version: \(infoPlist.bundleShortVersionString) (\(infoPlist.bundleVersion))
Matrix SDK version: \(sdkGitSha())
\(device.model) \(device.systemVersion)
"""
}
}