Embracing errors is a good idea

I remember distincly when I read the article called “A More Useful 404”. I immediately added similar logic to my own sites, and while sifting through piles of email logs telling me about how IE6 does the weirdest CSS searching EVER, the emails have proved really useful to track down missing pages or especially missing redirects when a site is being rebranded & reogranized.

I felt the same wave of excitement when I learned about Crittercism. Once again, I immediately installed it in all the apps I was working on. With Crittercism, you will get an email whenever an unexpected crash occurs, but even better, you can present the user with a dialogue that collects some input from them. Suh-huh-huh-weeeet. If you give a darn about having good UX, this should be making you smile.

Must we always create an empty project!?

I wish the motion command could be modified to use project scaffolds. Then I could just say “run motion create -s colinta foo!”. But alas, we cannot.

Someone add this ability to https://github.com/HipByte/RubyMotion/blob/master/lib/motion/project/app.rb. I am le tired.

  • motion create crittercism
  • cd crittercism
  • rvm use 1.9.3
  • rvm gemset create crittercism
  • rvm gemset use crittercism
  • gem install bundler
  • echo "source :rubygems"$'\n'"gem 'sugarcube'" > Gemfile
  • bundle install
  • Modify the Rakefile:

    “`ruby require ‘motion/project’


    require ‘bundler’ Bundler.require


  • Modify app_delegate.rb

    “`ruby class AppDelegate def application(application, didFinishLaunchingWithOptions:launchOptions) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) ctlr = UINavigationController.alloc.initWithRootViewController(FirstController.new) @window.rootViewController = ctlr

    @window.makeKeyAndVisible true end end

    class FirstController < UIViewController end ”`

Let’s get this party started

To install Crittercism, we start at their site, so go there now.

  1. Signup
  2. Go to downloads
  3. Go ahead and grab the “with in-app support forum”, we’ll play with that in this tutorial.

We’re going to dump that zip file (at the time of this writing, 30 Sep 2012, the latest stable version is 3.3.4) into a vendor folder. So mkdir vendor && cd vendor && unzip ~/Downloads/Crittercism_v3_*.zip && cd ..

All we really need is the CrittercismSDK folder, so I would rm the Docs and CrittercismExampleApp folders, but I leave that to you.

Now we add it as a vendor’d project. In your Rakefile, we need to add CrittercismSDK and add a couple frameworks that Crittercism depends on:


Motion::Project::App.setup do |app| # Use `rake config' to see complete project settings. app.name = ‘crittercism’

app.vendorproject(‘vendor/CrittercismSDK’, :static, :headersdir => ‘vendor/CrittercismSDK’) app.frameworks << ‘SystemConfiguration’ app.frameworks << ‘Crittercism’ end ”`

You can run rake build now if you want to see the SDK compile:

> rake build
     Build ./build/iPhoneSimulator-6.0-Development
     Build vendor/CrittercismSDK   # <= that's all you get!
# ...

To get this running in our AppDelegate, we will need an AppID. So, we need to MAKE an AppID! https://www.crittercism.com/developers, and click the big “Register a New Application” button.

Register a New Application

I’ll call mine “CrittercismTest”, but you can call yours “My Uncle Bob” if you want. You’ll end up back in the Apps section, click your newly created app, and then hop over to Settings. You just need the AppID, don’t bother with the initialize code. As of today, the code is wrong anyway (well, it’s outdated - it’ll still work)

“`ruby class AppDelegate def application(application, didFinishLaunchingWithOptions:launchOptions) @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds) ctlr = UINavigationController.alloc.initWithRootViewController(FirstController.new) @window.rootViewController = ctlr

app_id = "12345yourappidhere67890"
Crittercism.initWithAppID(app_id, andMainViewController:ctlr)


end end ”`

You can see the correct initialize code if you go to the docs section, btw.

And you should, because if you scroll down, you’ll see a few more quick examples, of simple error handling (aka “it just works”) and leaving a breadcrumb trail. It’s like debugging with simple calls to NSLog, but you only see them when a crash occurs, which in this case is what we care about (in my imagination, Crittercism comes in at the “beta” phase, not during initial development).

Make it do something!

(I have this code in app_delegate, because this is such a small example)


“`ruby class FirstController < UIViewController

def viewDidLoad crashbutton = UIButton.rounded crashbutton.frame = [[0, 0], [132, 20]] crashbutton.center = [self.view.frame.size.width/2.0, self.view.frame.size.height/2.0] crashbutton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth crashbutton.setTitle("Make my day.”, forState: :normal.uicontrolstate) crashbutton.on :touch do Crittercism.leaveBreadcrumb(“User pressed the crashbutton”) raise “ZOMG!!” end self.view << crashbutton end

end “`

> rake

Go ahead, press the button.

You get… nothing!

That’s because the crash isn’t sent until the app is run again. Them’s the rules. So run the app again.

You still get… nothing!

Wait one minute. I mean literally, wait one minute. Crash reports are "flushed” to the server after a minute, so if lots of crashes happen, you will get one email, not a bunch of them.

You get… an email!

It should look something like this:

Crittercism email report

Nice! We are on our way. If you have an enterprise account (or are in the trial period for one) you can add a breadcrumb trail. Let’s see what that is all about:

ruby crash_button.on :touch do Crittercism.leaveBreadcrumb("User pressed the button") raise "ZOMG!!" end

If you open a crash report now, you can view the breadcrumb trail.

Apps >
  CrittercismTest >
    Crash Reports >
      *click on an error* >
        Breadcrumbs tab

Get user feedback, even though you will hate what they have to say.

Yes, you will have to filter through some pretty asinine remarks. Sorry, but unless you want to change your market from humans to some other sentient race, dems the breaks.

Let’s add another button (because our crash button is working sooo well!) and have it display the Crittercism feedback controller.

ruby def viewDidLoad # ... feedback_button = UIButton.rounded feedback_button.frame = [[0, 0], [132, 20]] feedback_button.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth center = crash_button.center center.y += 40 feedback_button.center = center feedback_button.setTitle("Uh, this is stupid.", forState: :normal.uicontrolstate) feedback_button.on :touch do Crittercism.leaveBreadcrumb("User pressed the feedback_button") Crittercism.showCrittercism(self) end self.view << feedback_button end

When I run the app now, I end up with this:

  • crittercism_fail.png

    Crittercism Fail Png

Uh, Houston?

I was stumped by this until, of all things, I committed my files to git, and there I saw this huge amount of stuff in vendor/CrittercismSDK/Resources/. We probably need those… Because Crittercism has assumed that it is being used in an Objective-C project, none of the calls to [UIImage imageNamed:x] will use any folder prefix (which we can do, and I think should do, using RubyMotion). So, unfortunately, we will just have to put everything in the resources/ folder and it’s just gonna get all cluttered. :-/

Note: It would be neat if we could change or add other resource folders to the project.

> mv vendor/CrittercismSDK/Resources/Images/* resources/
> mv vendor/CrittercismSDK/Resources/Nibs/* resources/
> rake


  • crittercism_success1.png

    Crittercism Success1 Png

  • crittercism_success2.png

    Crittercism Success2 Png

  • crittercism_success3.png

    Crittercism Success3 Png

  • crittercism_success4.png

    Crittercism Success4 Png

  • crittercism_success5.png

    Crittercism Success5 Png

Now go forth and prosper!