PLCrashReporter 是一个可靠的开源库,为 iOS、macOS 和 tvOS 提供进程内实时崩溃报告框架。该库检测崩溃并生成报告,其中包含应用程序、系统、进程、线程等信息以及堆栈跟踪,以帮助您进行调查和故障排除。
使用 PLCrashReporter 最简单的方法是使用 AppCenter。 但是,如果您想直接使用 PLCrashReporter,请在发布页面获取最新版本。
崩溃报告以 protobuf 编码的消息输出,可以使用 CrashReporter 库或任何 Google Protocol Buffers 解码器进行解码。
除了库内解码支持之外,您还可以使用包含的 plcrashutil
二进制文件将崩溃报告转换为苹果的标准 iPhone 文本格式。
plcrashutil convert --format=iphone example_report.plcrash
您可以使用 atos
命令行工具来符号化输出。 有关此工具的更多信息,请参阅 为崩溃报告添加可识别的符号名称。 未来的库版本可能会包含内置的可重用格式化程序,用于直接从手机输出其他格式。
可以通过 CocoaPods, Carthage, Swift Package Manager 或手动将二进制文件添加到您的项目来将 PLCrashReporter 添加到您的应用程序。
Podfile
中pod 'PLCrashReporter'
pod install
以安装您新定义的 pod 并打开项目的 .xcworkspace
。Cartfile
中github "microsoft/plcrashreporter"
carthage update --use-xcframeworks
以获取依赖项。Frameworks, Libraries and Embedded Content
部分。 对于 iOS 和 tvOS,将 Embed
设置为 Do not embed
。 对于 macOS,将 Embed
设置为 Embed and Sign
。注意: Carthage 集成在 Xcode 12 中使用标志 "--no-use-binaries" 或从特定分支构建依赖项时无法正确构建。 要使其正常工作,请参考 此说明。
注意: PLCrashReporter xcframework 包含 iOS 和 tvOS 的静态二进制文件以及 macOS 的动态二进制文件。 将框架添加到您的项目时,请确保在
Frameworks, Libraries and Embedded Content
部分中,对于 iOS 和 tvOS,Embed
选择为Do not embed
,对于 macOS,选择Embed and Sign
。PLCrashReporter-Static-{version}.zip
是一个例外 - 它包含所有平台的静态框架。
以下示例显示了如何初始化崩溃报告器。 请注意,启用进程内崩溃报告会与任何附加的调试器冲突,因此请确保在应用程序崩溃时未附加调试器。
@import CrashReporter;
...
// Uncomment and implement isDebuggerAttached to safely run this code with a debugger.
// See: https://github.com/microsoft/plcrashreporter/blob/2dd862ce049e6f43feb355308dfc710f3af54c4d/Source/Crash%20Demo/main.m#L96
// if (![self isDebuggerAttached]) {
// It is strongly recommended that local symbolication only be enabled for non-release builds.
// Use PLCrashReporterSymbolicationStrategyNone for release versions.
PLCrashReporterConfig *config = [[PLCrashReporterConfig alloc] initWithSignalHandlerType: PLCrashReporterSignalHandlerTypeMach
symbolicationStrategy: PLCrashReporterSymbolicationStrategyAll];
PLCrashReporter *crashReporter = [[PLCrashReporter alloc] initWithConfiguration: config];
// Enable the Crash Reporter.
NSError *error;
if (![crashReporter enableCrashReporterAndReturnError: &error]) {
NSLog(@"Warning: Could not enable crash reporter: %@", error);
}
// }
可以通过以下方式检查收集的崩溃报告
if ([crashReporter hasPendingCrashReport]) {
NSError *error;
// Try loading the crash report.
NSData *data = [crashReporter loadPendingCrashReportDataAndReturnError: &error];
if (data == nil) {
NSLog(@"Failed to load crash report data: %@", error);
return;
}
// Retrieving crash reporter data.
PLCrashReport *report = [[PLCrashReport alloc] initWithData: data error: &error];
if (report == nil) {
NSLog(@"Failed to parse crash report: %@", error);
return;
}
// We could send the report from here, but we'll just print out some debugging info instead.
NSString *text = [PLCrashReportTextFormatter stringValueForCrashReport: report withTextFormat: PLCrashReportTextFormatiOS];
NSLog(@"%@", text);
// Purge the report.
[crashReporter purgePendingCrashReport];
}
import CrashReporter
...
// Uncomment and implement isDebuggerAttached to safely run this code with a debugger.
// See: https://github.com/microsoft/plcrashreporter/blob/2dd862ce049e6f43feb355308dfc710f3af54c4d/Source/Crash%20Demo/main.m#L96
// if (!isDebuggerAttached()) {
// It is strongly recommended that local symbolication only be enabled for non-release builds.
// Use [] for release versions.
let config = PLCrashReporterConfig(signalHandlerType: .mach, symbolicationStrategy: .all)
guard let crashReporter = PLCrashReporter(configuration: config) else {
print("Could not create an instance of PLCrashReporter")
return
}
// Enable the Crash Reporter.
do {
try crashReporter.enableAndReturnError()
} catch let error {
print("Warning: Could not enable crash reporter: \(error)")
}
// }
可以通过以下方式检查收集的崩溃报告
// Try loading the crash report.
if crashReporter.hasPendingCrashReport() {
do {
let data = try crashReporter.loadPendingCrashReportDataAndReturnError()
// Retrieving crash reporter data.
let report = try PLCrashReport(data: data)
// We could send the report from here, but we'll just print out some debugging info instead.
if let text = PLCrashReportTextFormatter.stringValue(for: report, with: PLCrashReportTextFormatiOS) {
print(text)
} else {
print("CrashReporter: can't convert report to text")
}
} catch let error {
print("CrashReporter failed to load and parse with error: \(error)")
}
}
// Purge the report.
crashReporter.purgePendingCrashReport()
此外,还使用以下可选工具来构建其他资源
protobuf-c
用于将 Protocol Buffer .proto
文件转换为 C 描述符代码。 有关更多信息,请参见 官方 protobuf-c 存储库,或使用 Homebrew 安装它。如果您修改了任何带有 .proto 扩展名的文件(例如 Tests/PLCrashLogWriterEncodingTests.proto
或 Source/PLCrashReport.proto
),则在构建项目之前,需要使用 protobuf-c
生成源文件。 为此,您可以运行以下脚本
./Dependencies/protobuf-c/generate-pb-c.sh
为您的终端打开一个新窗口。
转到 PLCrashReporter 的根文件夹并运行
xcodebuild -configuration Release -target 'CrashReporter'
为所有平台创建二进制文件。
要更新 protobuf-c
依赖项
protobuf-c.h
和 protobuf-c.c
文件。Dependencies/protobuf-c
中的现有文件替换为下载的文件。./Dependencies/protobuf-c/generate-pb-c.sh
我们期待您通过拉取请求贡献代码。
要为 PLCrashReporter 做出贡献,您需要上面提到的工具来为所有架构构建 PLCrashReporter,并使用 protobuf-c
将 Protocol Buffer .proto
文件转换为 C 描述符代码。
本项目已采用 Microsoft 开放源代码行为准则。 有关更多信息,请参阅 行为准则常见问题解答 或通过 opencode@microsoft.com 联系,提出任何其他问题或意见。