The Timer object allows you to measure the duration of an application operation. The duration is logged with the timestamp of the event and a key value that can be used for filtering analytics.

There are two ways developers can handle the Timer object:
  • Call the stop timeStart:key and timeEnd:key APIs. The library stores the Timer object, which is invisible to the application developer. The library keeps the timer in memory and persists it into the database when timeEnd:key is called. The key is mandatory and must be unique for each timer.
  • Call the +(Timer*)makeTimer:(NSString*)key API, which creates a timer instance and returns it to the application layer. The application stores the timer; the library does not keep references to it. To stop and persist the timer, the application calls +(void)stopTimer:(Timer *)timer. The key can be empty or duplicated.

The API timer is an object with a timestamp and a method to stop the timer, which sets the timer interval to the current time and saves the duration. After the timer stops, the Timer object is saved in the database.

Because the Timer object is handled in memory, it is well suited for passing into blocks or through delegate patterns. For example, the duration of an asynchronous sequence can be measured by creating a timer outside of a block, then calling the [Usage stopTimer:myTimer] method within the completion block created in the same context.


A developer wants to know how long it takes for data to appear on a screen. A timer captures how long it takes to download and parse the set of business partners from the network, and how long it takes to load the iOS Map View for the business partner's location.

The application uses two classes working together to load the initial view, the DataViewController and the ModelController. The view loads the UI, and subscribes to changes on the model; there is a subscription block in the DataViewController that is called when the view gets the BusinessPartner object from the ModelViewController.

Create a timer, then call stop when the download is complete:

// DataViewCollector.m
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // Developer should call [Usage makeTimer:<keyname>] in order to get Timer object
    Timer *myTimer = [Usage makeTimer:@"loadDataViewController"];

    [[RACObserve(self, dataObject) filter:^BOOL(id value) {
        return value != nil;
    }] subscribeNext:^(BusinessPartner *x) {                    

        // Here is the block called when BusinessPartner changes

        ...     // Some stuff to start loading the specific sales orders and contacts
                // for the business partner

        // Start to do some MapKit code, and set up the geocodeAddress creation
        CLGeocoder *geocoder = [[CLGeocoder alloc] init];

        NSString *venue= [NSString stringWithFormat:@"%@ %@, %@, %@, %@", x.building, x.street,,, x.postalCode];
        [geocoder geocodeAddressString:venue completionHandler:^(NSArray *placemarks, NSError *error)
            ...     //  Here's another completion block.  
                    //  Call the 'stopTimer' here

            [Usage stopTimer:myTimer];

The library generates a record that POSTs to the server:

    "timestamp" : "2014-03-31T14:23:53.841-0700",
    "key" : "loadDataViewController",
    "info" : {
        "start" : "2014-03-31T14:23:53.841-0700",
        "duration" : 790.3379797935486
    "type" : "timer",
    "appSessionId" : "eqjprxxjhish",
    "userSessionId" : "rtjozffvwutc"