Logging errors, exceptions and events with Google Analytics

I ran across a nice intro article to using assertions in iOS  Working with Assertions to Debug your Apps.   It describes the macros NSAssert, NSAssert1, NSAssert2, etc. and how to use them.   One item mentioned in that article is different in XCode now – the macro NS_BLOCK_ASSERTIONS is defined by default for Release builds.

The article started me thinking about how one might report crashes and user-generated assertions in a production app.   I came across the article Handling crashes and NSAssert gracefully in a Production App.  Not only does it talk about how to continue using assertions in a Release build by subclassing  NSAssertionHandler, but it also makes reference to using a service such as Flurry or Google Analytics to log them as well.

Flurry

Web searches showed that Flurry and Google Analytics are both nice choices for getting app metrics and logging errors/exceptions.   I spent some time looking through the Flurry web site and documentation and was impressed with what I saw.    I found a nice article that talks about Flurry and includes a video on how to get started with it – Find errors in your iOS app before your users do!

Google Analytics provides real-time results

Given that I had used Google Analytics in the past and was comfortable with it, I decided to try using their service for my logging needs first.

The one hesitation I had was that it was mentioned in several places that an advantage Flurry had over Google Analytics was in their update frequency.  Reportedly Flurry results were updated several times a day, whereas logging to Google Analytics required you to wait a day to see the results.

I can happily report that Google Analytics is in fact updating results to your Dashboard in near real-time (perhaps this was a more recent change).   I consistently saw updates within minutes of logging with their API.    You will however need to set a custom date range which includes the current day as shown below:

Google Analytics Custom Date Range 2

You may also need to choose a higher precision of reporting to get the real-time results as the following screenshot shows:

Google Analytics Visit Precision

Getting started with Google Analytics

It was pretty simple to get up and running with Google Analytics.   Their documentation for iOS starts with the section Google Analytics SDK for iOS v2.

You first need to go the Admin section of Google Analytics and click on + New Property (web or app).  Follow the prompts and you will be given a Tracking ID.  You’ll need this ID as you perform your initial setup using the SDK.

Initial Setup

After downloading the SDK you’ll need to copy some files to your project and link in a few frameworks per the instructions.   After that the setup basically involves importing the header GAI.h and adding some code to your AppDelegate.m file.   You will need to add your Tracking ID in the call to trackerWithTrackingId as shown below:


#import "GAI.h"

...

@implementation ContactsAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    // Optional: automatically send uncaught exceptions to Google Analytics.
    [GAI sharedInstance].trackUncaughtExceptions = YES;

    // Optional: set Google Analytics dispatch interval to e.g. 20 seconds.
    [GAI sharedInstance].dispatchInterval = 20;

    // The Google Analytics SDK for iOS provides a debug mode that will print useful information
    // about what data is being sent to Google Analytics in your logs.
    //
    // Disable debug mode.  On by default.
    [GAI sharedInstance].debug = NO;

    // Create tracker instance.
    [[GAI sharedInstance] trackerWithTrackingId:@"Your tracking id"];

    return YES;
}

Tracking your view controllers

The first thing I learned how to do with Google Analytics is to track which view controllers were being hit for the Screens report:

Google Analytics Screens

The report is available under the Engagement section.   Here I am showing a logging of my view controller EntryViewController.

How did I create this entry with the API?

There are two methods.  I chose to have this done automatically for me by deriving from the class GAITrackedViewController, a convenience class that extends UIViewController.


#import "GAITrackedViewController.h"

@interface EntryViewController : GAITrackedViewController

You also need to specify the view name for the reports.


- (void)viewDidLoad
{
    [super viewDidLoad];
    self.trackedViewName = @"EntryViewController";
    ...
}

Alternatively you can register a Screen view manually with a call such as:

    id defaultTracker = [GAI sharedInstance].defaultTracker;
    [defaultTracker sendView:@"EntryViewController"];

Logging Events

You might be interested in logging at a finer level than just Screen views.  There is an Event Tracking mechanism that allows you to report an event broken down by category, action, label and value.

The call looks like the following where can you use any made up NSString for category, action, and label as well as an optional NSNumber (64 bit integer) as the value:


[tracker sendEventWithCategory:@"uiAction"
withAction:@"buttonPress"
withLabel:buttonName
withValue:[NSNumber numberWithInt:100]];

The following shows what some API event calls will look like in the Dashboard:

Google Analytics Events

Exceptions and Errors

Logging exceptions and errors was what I had initially had in mind with Google Analytics and it does a nice job of handling them.

There are caught and uncaught exceptions.  An uncaught exception is one that is not handled directly in your code – for example in a @try { } @catch { } block.

By setting [GAI sharedInstance].trackUncaughtExceptions = YES as shown in the setup above, these uncaught exceptions will be sent automatically for you.

Caught exceptions are reported to Google Analytics as either fatal or non-fatal.  The three varieties of API calls have the signatures:


[tracker sendException:(BOOL) withDescription:(NSString *)]

[tracker sendException:(BOOL) withNSError:(NSError *)]

[tracker sendException:(BOOL) withNSException:(NSException *)]

Here the BOOL is set to NO for non-fatal and YES for fatal.

An example of what this might look like in the Dashboard is:

Google Analytics Exceptions

For the data above, I first made an API call for a non-fatal exception (Network connection timed out). I then made an API call for a fatal exception (File corruption detected) followed by throwing an NSInternalInconsistencyException using code such as:


[NSException raise:NSInternalInconsistencyException format:@"EXCEPTION in ..."]

You will note that both the API call I made for a fatal exception, as well as the uncaught exception I triggered with raise:NSInternalInconsistencyException were represented as Crashes in the report (fatal). All 3 entries in the report are classified as Exceptions.

Advertisements

2 responses to “Logging errors, exceptions and events with Google Analytics

  1. Pingback: The development of Contacts2Web | Finalize.com: My journey with iOS and other code adventures

  2. I can’t find these apis in the latest Google analytics SDK (v3.11). Do we have an alternative?

    [tracker sendException:(BOOL) withDescription:(NSString *)]
    [tracker sendException:(BOOL) withNSError:(NSError *)]
    [tracker sendException:(BOOL) withNSException:(NSException *)]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s