Thursday, September 18, 2014

Track.js and Non-Legitimate Errors

So I've been talking about Track.js, and how it collects JavaScript errors on your site in one tidy dashboard.  It also sends you a daily summary email.  

If all the errors it sends were legitimate, everything would be great.  Unfortunately, JavaScript errors can be caused by things totally beyond-your-control.  For example, here's a recent daily report we received:


And we notice a couple of things right off the bat:

  • Error messages can happen in all different languages, like Chinese.  If you can't read it, you probably have no hope of debugging it!  If this is a legitimate error, you just have to hope someone hits the same error in your native language.
  • Errors can be really vague.  "Invalid procedure call or argument" might just as well read "Ooops.  Something happened."
  • Errors can reference functions you've never seen before.  That syncBFPerformOnDOMChanged looks awfully strange.
Let's drill down to the error screen on that last one:



The fact that it happened in Mac OS X and Safari, but not any other browser, is a sign something might be amiss with a plugin.  If you plugin in that nasty function name into Google, you get almost no hits.   Well ... if it isn't in your code base, and it isn't in a third party library you're using, you can't do anything about this error. 

Fortunately, Track.js lets you filter out error messages that you can do nothing about.   Here's the code we use:

<script>
  window._trackJs = {
    onError: function (payload) {
       var messagesToIgnore = [
        new RegExp("ReferenceError: Can't find variable: dataKeys", "ig"),
       new RegExp("'fidoCallback' is undefined", "ig"),
new RegExp("addthis_(open|close)", "ig"),
new RegExp("Error calling method on NPObject","ig")
       ]
       for (var i=0; i < messagesToIgnore.length; i++) {
 if (messagesToIgnore[i].test(payload.message)) {
   return false;
 }
       }
       return true; 
     }
  }
</script>

That way, if we run into another problem that can do nothing about, we simply add another regular expression to this list.  You can also do more sophisticated checks like "If this happens in IE 6 or below, ignore it."

The bottom line: trying to get to 0 JavaScript errors in a public-facing site is not a good goal.  You never know what browser plugins are screwing around with your JavaScript, and you can't prevent that rogue user using Mosaic 0.1.  We've even seen BOTS that try to execute JavaScript code very naively, and barf up head-scratching errors.  

However, we've found the following strategy works great with Track.js:
  • If the error rate goes up sharply on a certain day, it's worth checking out.  Usually you can trace it back to a recent production change, or a particular edge case that just happened that day.
  • If someone independently reports an error your site, and they can give you a rough URL and timeframe, the Track.js dashboard can help you pinpoint it.  

Tuesday, July 29, 2014

Using Track:Js for a Legitimate Error

Using Track:Js, it's becoming clear there are two kinds of JavaScript errors:

  • Non-legitimate ones.  These are caused by buggy browsers or their respective plugins.  They usually don't affect site performance at all.
  • Legitimate ones.
The trick is deciding which category your error belongs to.   That's an art, and there are no hard and fast rules.  But there are some good heuristics, and Track:Js definitely helps you out there.  

I get a daily summary email from Track:Js with statistics and the top errors.  This morning I found:


The TypeError: 'undefined' is not an object error interests me a little.  It's a little generic, and generic errors are harder to track down.  But it "feels" like an error I'd make.  So I click on that error to get the hits in the Track:Js dashboard.

So here I got three errors around 5:11 on the same page, but with a legitimate modern browser.  (I do not consider WebThumb a legitimate one, nor ones like IE 5.)  So I pull it up in my browser of choice, Chrom on Ubuntu.  Sure enough the console says:



Which brings me to the most important differentiator of legitimate and non-legitimate bugs:
If it doesn't work in MY browser, it's a legitimate bug!
OK, that's kind of flippant.  But the next time I touch this page, I won't know if the bug is caused by my changes or not.  So I had better fix it.

Fortunately, Chrome gives nicer error messages than Safari, so I can Google this particular problem.  Searching for Cannot read property msie of undefined I get the following helpful post:

http://stackoverflow.com/questions/14793331/uncaught-typeerror-cannot-read-property-msie-of-undefined

And basically it confirms what I've run into before about jQuery.  Something is trying to use an old, deprecated-then-removed feature, and it looks like jquery-ui is the culprit.  Nicely, Track:Js tells me all the versions of the libraries that are loaded:

So we're trying to use jQuery 1.11 (a very new version at the time of this writing) with jQuery-UI 1.8 (which was released around 2010 or so).  I check the page source and find we're not loading jQuery-UI on our own.  Instead, it seems to be coming from the OpenTable script we're loading.  

After a few minutes, I find I can just pop in the jQuery Migrate plugin to make jQuery-UI 1.8 and jQuery 1.11 play nice together.  That's just:

<script type="text/javascript" src="https://code.jquery.com/jquery-migrate-1.2.1.min.js">

The error disappears from Chrome, so I release it to the wild.  Track:Js helped me in a couple of different ways here - not just identifying the error but providing me some good info on the context around it.  




Friday, July 25, 2014

Track:js: Hello World!

Like many web programmers, I wear two programming hats.  One hat is for the server-side, and whenever I make a mistake on the server side, bells and whistles go off, I get an email with a stakc trace, plus a Growl alert, a siren, and my cat arches his back and hisses.  I know right away when there is trouble in paradise.

The other hat is for the client-side.  Ugggh.  In JavaScript, no one will hear you scream.  When your little JavaScript snippet blows up, it leaves your page in a precarious half-useful state.  It might look OK but when you start trying to do stuff, things just don't work.  As a programmer you're used to this crap happening, and you start up FireBug or Developer Tools or what have you, more-or-less out of habit. You even do it on other people's sites.

But when your customers encounter an error, they immediately go to your competitor's site.  The problem has been around since Mosaic 0.1 beta.  You, as a programmer, need an alert when JavaScript blows up on the client's browser, wherever that may be.

Enter track:js. Think of it as an sniffer, logger and aggregator for all your site's JavaScript errors.   Pretty nice, but does it tamper with the user experience?  Do they need browser plugins, or the beta version of browser X that's not due until next year?  Nope.  Track:js does it's magic all with standard JavaScript.  That proves what you've known all along - JavaScript is tremendously powerful, even if it's  still a PITA.   Track:js seems to leverage it to the n'th degree.

We're total sceptics at the Cornell School of Hotel Administration, so we got a trial key and gave it a whirl.  We just popped this into our standard header:



And away we go.  After a few days we checked the handsome looking dashboard to see what's up.



It's a little bit of a shock to see your perfect website generating JavaScript errors that you've never heard about.  Surely it wasn't YOUR code, was it?  Did gremlins get hold of your Github account?  Ah well.  In the next day or two, we'll see what's up.

Oh, and all this nice stat gathering doesn't seem to affect performance.  The site is still nice and peppy.  So far, so good.