3

Apple introduced Activity Tracing to support debugging asynchronous code. I have some difficulties using it properly. My example scenario is a small MacOS app just downloading a file:

- (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];
    });
}

Filtering for my messages in Console.app I am getting:

Console messages

Obviously NSURLSession does not call the completionHandler with the same activity active that initiated the download. I had to manually apply that activity within the callback. Is there a better way to do this? I thought that activities are designed to trace things across process. In that case it is not even working inside the same process without doing some extra work.

In the activity view of the Console.appI am getting:

Console activities

The tree view looks promising, to get a quick overview about what application scenarios are triggered. Initially I thought that it is not necessary to apply a new activity in an action callback and instead it would be possible to use os_activity_label_useraction to get the scenario displayed in Console.appactivity view on top level. Obviously that's not the case. I can't find that label in any log.

My solution is to create a new detached activity in actionDownload. This activity is visible on top level in the Console.appactivity view. What I dislike with this solution are two things:

First, I had to explicitly create a new activity with a new scope. This adds lots of noise to the source code. I have many very short action methods in my project. Also the messages view works without this. There I am just getting what I am interested in by filtering for subsystem, category and activity id.

Second, the connection to the initiating activity gets lost.

Would be great to get some hints about how to properly use Activity Tracing and especially the hierarchy thingy.

Bokeh
  • 77
  • 1
  • 7

0 Answers0