Using HP AppPulse With iOS
Written by Benjamin Garrigues   
Thursday, 28 January 2016
Article Index
Using HP AppPulse With iOS
User-centric error reporting

 

Errors on "Done"

Just like "Close," marking a To-do task as "Done" can also trigger errors. This time, however, the kind of errors it can trigger are not only alert messages, but network errors as well.

HTTP Errors

Most first-party web service failures will probably be detected by your server-side monitoring tools. Yet whenever your app is using a third party API, you are potentially exposed to issues in its quality of service. Since users won't make the distinction between what's your responsibility and what isn't, monitoring HTTP errors is crucial for user satisfaction control.

And since we're trying to post a tweet every time a user marks a to-do as "Done," we can get the Twitter API return 403 HTTP errors upon quotas limits, API endpoint deprecation, or message deduplication.

Note that you don't have to add anything to your code for these errors to be reported.

In our case, we decided to also show an alert message if we failed to post the tweet, to warn the user that something went wrong.

Picture7

 

Picture8

Here's the code that does that:

func postTodoOnTwitter(todo:Todo){
 guard let todoTitle = todo.title
      where todo.title != nil else {
           return
      } 
      self.checkTwitterAccount {
       (twitterAccount:ACAccount) -> Void in
 
          let requestURL = NSURL(string:
                  "https://api.twitter.com/1.1/
                       statuses/update.json")

      let slRequest = SLRequest(
         forServiceType: SLServiceTypeTwitter,
         requestMethod: SLRequestMethod.POST,
         URL: requestURL,
         parameters: ["status":todoTitle+"done"])
      slRequest.account = twitterAccount
      slRequest.performRequestWithHandler {(
         data:NSData!,
         response:NSHTTPURLResponse!,
         error:NSError!) -> Void in
     if(response != nil &&
                       response.statusCode == 200){
         todo.tweetedAt = NSDate()
         try!self.appDelegate.
                     managedObjectContext.save()
     } else {
         let errorDesc = (error != nil ?
                    error.localizedDescription :
             NSLocalizedString(
                "Unknown error",
                 comment:"Unknown error"))
         let title = NSLocalizedString(
                "Twitter Posting Error",
                comment:"Error Alert title")
         let message = NSLocalizedString(
           "Could not post to twitter account : \n",
            comment:"Twitter post error")
                                    + errorDesc
         let buttonText:String = NSLocalizedString(
            "Ok", comment: "Ok button")
    /* alert view style */
         let alertView = UIAlertView(
           title:title,
           message: message,
           delegate: nil,
           cancelButtonTitle: buttonText)

         dispatch_async(dispatch_get_main_queue(),
              { () -> Void in
                 alertView.show()
              })
          }
        }
     }

 }

Failed Action Synthetic View

AppPulse Mobile provides error reporting based on user actions. Instead of simply logging errors per error type on various boards (e.g. list of HTTP errors, list of UI Alert errors, etc.), AppPulse Mobile records which user action is at the origin of these multiple errors, and displays them under a single meaningful entry - one per each type of user action.


By looking at the interface, you can see that the "Done" action has also triggered some errors:

 

Picture9


Yet this time, when you dive into the details of this action you can see that both network and UI alert errors are involved:

 

Picture10


This type of reporting provides you with a unique user-centric view of the errors, rather than a purely technical one.

App Launch / Manual SDK Error

Many things can go wrong when launching an app. In our example - since we're using CoreData - problems may arise when initializing the local DB. AppPulse Mobile automatically detects and reports crashes and unhandled exceptions, but errors sometimes need to be reported manually using code. For this you can use the AppPulse Mobile framework functions directly.

Here's the full list of methods you can use once you've included the <AppPulsemobile/HPAppPulse.h> header:


+ (void) setScreenName:(UIViewController*)
         vc screenName:(NSString*)name;

+ (void) setControlName:(UIView*)
      control controlName:(NSString*)controlName;

+ (void) setControlName:(UIView*)
      control controlName:(NSString*)controlName
       withScreenName:(NSString*)screenName;

+ (void) setControlType:(UIView*)
      control controlType:(HPControlType)type;

+ (void) addBreadcrumb:(NSString *)text;

+ (void) reportCrash: (NSException*) exception;

+ (void) reportHandledException:(NSException *)
   exception withDescription:
            (NSString *)description;

+ (void) reportHandledException:
                   (NSException *)exception;

 

At the moment, only report HandledException is officially supported.

NOTE: When coding in Swift, you may have to bridge the HPAppPulse.h file before using it. For that, first create a "Bridge-Header.h" file that contains only one line:

#import <AppPulsemobile/HPAppPulse.h>

Then, in the build settings of the target, add this file in an "Object-C Bridging Header" entry under the "Swift Compiler - Code Generation" section. You will then be able to use HPAppPulse methods right from your swift code.

In our case, Xcode's template for apps using CoreData already catches thrown exceptions; we simply catch any exception thrown during the persistent store coordinator initialization, and report it.

do {
    try coordinator.addPersistentStoreWithType(
           NSSQLiteStoreType,
           configuration: nil,
           URL: url,
           options: nil)
    } catch {
// Report any error we got.
      var dict = [String: AnyObject]()
      dict[NSLocalizedDescriptionKey] =
           "Failed to initialize the
                    application's saved data"
      dict[NSLocalizedFailureReasonErrorKey] =
                                    failureReason
      dict[NSUnderlyingErrorKey] = error as NSError
      let wrappedError = NSError(
          domain: "CoreData initialization",
          code: 9999,
          userInfo: dict)
// Replace this with code to handle the error
// appropriately.
// abort() causes the application to generate a
// crash log and terminate. You should not use this
// function in a shipping application,
// although it may be useful during development.
      NSLog("Unresolved error \(wrappedError),
                     \wrappedError.userInfo)")
      HPAppPulse.reportHandledException(
           NSException(name: wrappedError.domain,
              reason: wrappedError.description,
               userInfo: dict))
      abort()
   }


To test this error, we install the app on a device to have it create the DB file, then make a random modification to the core data model (such as adding a dummy boolean field) - and forget to create a migration file.

Here's how the error would appear in the interface: 

Picture11

 
And here are the details: 

Picture12

 

We've seen how AppPulse Mobile is able to report most unexpected behaviors - from UI Alerts to HTTP errors - automatically, and group them under the user action at their origin, so that you can easily get a comprehensive view of the features that lead to errors. We've also explored how to manually send errors to be displayed in the AppPulse Mobile interface, should you need it.  By using AppPulse Mobile, you can be sure that no error or unexpected behavior will remain unnoticed.

  • Benjamin Garrigues is a senior application developer and architect and founder of Simple App, an IT consulting company focused on modern IT architectures answering today's companies needs for service omnipresence at affordable cost.

 AppPulse2

More Information

HP App Pulse Mobile

Related Articles

Animated iOS User Interfaces

Analytics As A Service 

Monitor Mobile 

Deep Monitor Your Site 

Banner

 

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on, Twitter, FacebookGoogle+ or Linkedin

 

 



Last Updated ( Tuesday, 02 February 2016 )