83 lines
2.8 KiB
Swift
83 lines
2.8 KiB
Swift
import CrashReporter
|
|
import Foundation
|
|
import os
|
|
|
|
public enum NativeCrashReporter {
|
|
private static let logger = Logger(category: "NativeCrashReporter")
|
|
private static let installLock = NSLock()
|
|
private static var reporter: PLCrashReporter?
|
|
|
|
public static func installForCurrentProcess(basePath: URL? = nil) {
|
|
installLock.lock()
|
|
defer {
|
|
installLock.unlock()
|
|
}
|
|
|
|
guard reporter == nil else {
|
|
return
|
|
}
|
|
|
|
let crashBasePath = basePath ?? CrashReportArchive.pendingNativeCrashBaseDirectory
|
|
do {
|
|
try FileManager.default.createDirectory(at: crashBasePath, withIntermediateDirectories: true)
|
|
let config = PLCrashReporterConfig(
|
|
signalHandlerType: .BSD,
|
|
symbolicationStrategy: [],
|
|
basePath: crashBasePath.path
|
|
)
|
|
guard let crashReporter = PLCrashReporter(configuration: config) else {
|
|
logger.warning("Failed to create PLCrashReporter instance")
|
|
return
|
|
}
|
|
try crashReporter.enableAndReturnError()
|
|
reporter = crashReporter
|
|
} catch {
|
|
logger.warning("Failed to enable native crash reporting: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
|
|
public static func loadAndPurgePendingCrashReportData() -> Data? {
|
|
installLock.lock()
|
|
guard let reporter else {
|
|
installLock.unlock()
|
|
return nil
|
|
}
|
|
installLock.unlock()
|
|
|
|
guard reporter.hasPendingCrashReport() else {
|
|
return nil
|
|
}
|
|
|
|
let data = try? reporter.loadPendingCrashReportDataAndReturnError()
|
|
reporter.purgePendingCrashReport()
|
|
return data
|
|
}
|
|
|
|
public static func archiveLiveReportForCurrentProcess() {
|
|
installLock.lock()
|
|
guard let reporter else {
|
|
installLock.unlock()
|
|
return
|
|
}
|
|
installLock.unlock()
|
|
|
|
do {
|
|
let data = try reporter.generateLiveReportAndReturnError()
|
|
let crashReport = try PLCrashReport(data: data)
|
|
guard let text = PLCrashReportTextFormatter.stringValue(for: crashReport, with: PLCrashReportTextFormatiOS),
|
|
!text.isEmpty
|
|
else {
|
|
return
|
|
}
|
|
let crashDate = crashReport.systemInfo.timestamp ?? Date()
|
|
_ = try CrashReportArchive.writeArchivedReport(
|
|
contents: CrashReportArtifactContents(nativeLog: text),
|
|
date: crashDate,
|
|
metadata: CrashReportMetadataBuilder.nativeMetadata(for: crashReport, content: text, source: "Application")
|
|
)
|
|
} catch {
|
|
logger.warning("Failed to archive live native crash report: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
}
|