我有一个测试版 iOS 应用程序,通过 TestFlight 分发给测试人员。有时,这些测试人员遇到的错误不会触发崩溃,但会导致体验下降。我使用
os_log
和错误日志级别记录所有这些错误,但我不确定如何检索日志,除非我物理连接他们的设备并在控制台中查看日志。
例如,应用程序在创建帐户时可能会遇到未知错误。该应用程序会显示一条警报,通知用户发生了错误,然后用
os_log
记录错误的详细信息。
import UIKit
import os.log
class MyViewController: UIViewController {
func signUpButtonTapped() {
do {
// Try to create the user's account, which might throw an exception.
try createUserAccount()
} catch {
os_log("Unknown sign up error: %@", log: .default, type: .error, String(describing: error))
let alert = UIAlertController(title: "Sign Up Error", message: "There was an error creating your account.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default))
present(alert, animated: true)
}
}
}
是否可以通过 TestFlight 检索这些记录的错误消息?或者,测试人员是否有内置方法可以手动向我发送应用程序的日志?我只遇到过检索崩溃日志的方法,但这种方法不起作用,因为错误不会触发崩溃。
我知道有第三方服务/库可以完成此任务,但我不想添加其他依赖项。
看起来无法从 TestFlight 用户远程检索日志。
我确实找到了一种让用户可以用
sysdiagnose
手动发送日志的方法,但是有点麻烦。详细信息由 Apple 记录在此处(您必须登录 Apple 开发者帐户才能查看链接)。我遵循与另一个答案相同的步骤,该步骤介绍了如何检索os_log
消息。
基本步骤是:
您可以使用 OSLog 框架来完成此操作,假设您运行的设备具有 iOS 或 MacOS 版本,其中错误已通过 OSLog 解决。在 15 或更高版本的 iOS 和 MacOS 上,它似乎可以返回到 11。
我构建了一个小实用程序来检索我需要调查的应用程序某个区域的 OSLog 条目,然后将其连接到一个按钮以允许用户将日志语句通过电子邮件发送到我们的支持电子邮件。
在我的实用程序类 init 方法中,我为 CoreData 和 CloudKit 设置了 OSLog 子系统,如下所示:
let coreDataLogSubsystem = "com.MyApp.coreData"
let coreDataLogger = Logger(subsystem:"com.MyApp.coreData", category:"Cloudkit")
我的 CoreData 实用程序类有一个像这样的例程,用于获取我的 CoreData 子系统的所有日志条目。它只是返回一个格式良好的长字符串,我将其附加到用户可以从应用程序内发送给我们的电子邮件中。
//
// Returns the log entries for CoreDataSubsystem from last 30 minutes.
// Currently App Delegate can use to append to Help Email for debug.
//
@objc func logEntries() -> String
{
var logStore : OSLogStore
do {
logStore = try OSLogStore(scope: .currentProcessIdentifier)
}
catch {
return "ERROR: Log Store NOT AVAILABLE"
}
// Fetch log objects.
let format = "subsystem == '\(coreDataLogSubsystem)'"
let predicate = NSPredicate(format:format)
let oneHourAgo = logStore.position(date: Date().addingTimeInterval(-1800)) // last 30 minutes
do {
let entries = try logStore.getEntries(with:[], at:oneHourAgo, matching:predicate)
var logEntryString = "\n************************\n"
for entry in entries {
logEntryString = logEntryString + "\(entry.date)" + ": " + entry.composedMessage + "\n"
}
return (logEntryString + "************************\n")
}
catch { return "ERROR: Could NOT get Log Entries"}
}
这种方法使我们能够基本上了解正在发生的情况,通过更多日志记录或修复要求 testflight 用户发送和发送电子邮件并重复冲洗来调整 TestFlight 构建。