Apple 引入了 Activity Tracing 来支持调试异步代码。我在正确使用它时遇到了一些困难。我的示例场景是一个小型 MacOS 应用程序,它只是下载一个文件:
- (IBAction)actionDownload:(NSButton *)sender {
os_activity_label_useraction("actionDownload");
os_log_t logDemo = os_log_create("ActivityTracingDemo", "demo");
os_log_debug(logDemo, "actionDownload start (1)");
os_activity_t actTop = os_activity_create(
"HTTP Download",
OS_ACTIVITY_NONE,
OS_ACTIVITY_FLAG_DETACHED);
os_activity_apply(actTop, ^{
os_log_debug(logDemo, "actionDownload start");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(2 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
os_log_debug(logDemo,
"actionDownload two second later");
});
NSURL *url = [NSURL URLWithString:
@"https://www.google.de/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png"];
// Get the current activity (or create a new one,
// if no current activity exists):
os_activity_t act = os_activity_create(
"HTTP Response",
OS_ACTIVITY_CURRENT,
OS_ACTIVITY_FLAG_IF_NONE_PRESENT);
NSURLSessionDownloadTask *downloadPhotoTask =
[ [NSURLSession sharedSession]
downloadTaskWithURL:url
completionHandler:^(NSURL *location,
NSURLResponse *response,
NSError *error)
{
os_activity_apply(act, ^{
// Now the same activity is active,
// that initiated the download.
os_log_debug(logDemo, "actionDownload received data (restored activity)");
});
os_log_debug(logDemo, "actionDownload received data");
}];
[downloadPhotoTask resume];
});
}
过滤我Console.app
收到的消息:
显然NSURLSession
不会调用completionHandler
与启动下载相同的活动。我必须在回调中手动应用该活动。有一个更好的方法吗?我认为活动旨在跨流程跟踪事物。在这种情况下,如果不做一些额外的工作,它甚至不能在同一个进程中工作。
在Console.app
我得到的活动视图中:
树视图看起来很有希望,可以快速了解触发了哪些应用场景。最初我认为没有必要在操作回调中应用新活动,而是可以使用它os_activity_label_useraction
来让场景显示在Console.app
顶级活动视图中。显然情况并非如此。我在任何日志中都找不到该标签。
我的解决方案是在actionDownload
. Console.app
此活动在活动视图的顶层可见。我不喜欢这个解决方案有两点:
首先,我必须明确地创建一个具有新范围的新活动。这给源代码增加了很多噪音。我的项目中有许多非常简短的操作方法。如果没有这个,消息视图也可以工作。在那里,我只是通过过滤子系统、类别和活动 ID 来获得我感兴趣的内容。
其次,与启动活动的连接丢失。
获得有关如何正确使用活动跟踪,尤其是层次结构的一些提示会很棒。