Tuesday, 24 June 2014

Source Maps Are Here!

In the previous blog post I talked about the exciting new feature of highlighting exactly where the error is, in your code. The fact that this is even possible to do externally, is the kind of stuff that distinguishes JavaScript from all other languages. It is why Errorception has this singular focus on JavaScript.

This post is to highlight one more such feature — source maps.

If you have errors in your minified code and Errorception's crawler discovers a source-map file associated with your code, it downloads the source-map file and your associated original source files, and versions & saves it in Errorception's file store. After that, all the goodness of pointing out the error isn't just applied to your minified file, but also to your original source-code.

Mapped! Showing you the error in your un-minified source!

Errorception shows you exactly where the error is in your original, unminified source-code. Not just that, it does all of this automatically, and across all your stack frames! Isn't that just awesome?

You just need to make your source-map file available, and Errorception will do the rest. The tweaks needed to your build script are real simple too — it's usually just a flag in most minifiers.

Your minified code is just a click away. Note the tabs at the top-right of your code.

Source maps have been around for some time now. However, I didn't want to implement source maps just so Errorception could wear it as a badge — I wanted to make it actually useful to you. The previous release was a step in this direction — putting your code front and center, and pointing out exactly where the error was in your deployed code. Now, source-maps completes this by not only pointing out exactly the token that caused the error, but also by doing so in your original unminified source file.

Oh, and of course, this also means that Errorception now supports compile-to-JS languages as well. CoffeeScript, TypeScript, ClojureScript and others, welcome to Errorception! You should feel at home.

As always, suggestions and feedback always welcome. Mail, Tweet, or leave a comment below.

Thursday, 19 June 2014

Here's Your Error!

Today's release is a game changer!

Now, whenever possible, your code and stack-traces take center stage in your error reports. Errorception looks at your code and the data from the error, and attempts to point out where exactly in your source file the error occurred.

Although the logic that points out your errors only gets incomplete data to work with, the predictions it makes about the error's cause are stunningly accurate in most cases. Not only does it point out the exact line and column number of the error, it also tries to make sense of your code to find the exact keyword or token that caused the error. And it does this across all stack frames!

Two stack frames of an error

See that screaming out: "Here's your error!" Isn't it just amazing how accurate it is? Do you see how easily you will be able to smash bugs with this?

Browser support

This feature relies somewhat heavily on stack-traces being available. All recent versions of Chrome (Desktop and Android) provide stack-traces in window.onerror out of the box, so you are already covered there. Stack-traces in window.onerror are new, having made it into the spec only recently. Firefox just implemented this about a week ago, so I expect the next release will ship with window.onerror stack traces. This also works for errors from IE10 for at least the first stack-frame, since IE10 provides a column number for every window.onerror error.

Additionally, this works just about everywhere if you .push your errors to Errorception. Until recently, Firefox didn't provide column numbers in their stacks, but that just got fixed a couple of days ago, expanding browser support to all popular browsers. In older versions of Firefox, you should still be able to see the highlight for the first stack-frame for .pushed errors.

It even works accurately with minified code!

If it isn't possible to highlight the offending keyword/token, Errorception will attempt to highlight the offending column. Errorception will definitely highlight the line of the error in all cases regardless.

The tech

The engineering needed to pull this off has been significant — certainly one of the more complex things I've worked on. At its heart lies a file-store, written from scratch, purpose-built for just this job. A crawler spiders your site for your JS files when errors occur, and saves them in the file-store, which caches and versions your files. This caching and versioning ensures that you see the rightest possible version of the file that caused the error, even if the file might have subsequently changed with new updates. Your files and the history of your error occurrences are then mined to figure out what might have caused the error.

There are no settings to be configured, no knobs to be turned — It All Just Works. Best of all, this is all done without any extra work on the client-side at all, so your users don't face any performance penalty whatsoever.

This release has been brewing for months, and has been in closed beta for a few weeks now. And today's feature isn't even the main reason I built all of this — it's just an awesome side-effect. But I'll save those details for the next blog post. (Can you spot it?)

As usual, feedback always welcome. Mail, Tweet or leave a comment below.

Tuesday, 25 March 2014

Fine-grained control over error posting

While Errorception has given you some control over error posting since a very long time, this has at best been very coarse-grained. Now, that gets fixed.

You now have full programmatic control over which errors get posted to Errorception. You just have to define _errs.allow to be a function that returns true or false. Examples are the best way to demonstrate this, so here goes:

To ignore all errors from say IE6:

_errs.allow = function() {
  return (navigator.userAgent.indexOf("MSIE 6") == -1);
}

To only allow errors from yourdomain.com and its subdomains:

_errs.allow = function() {
  return (location.hostname.indexOf("yourdomain.com") != -1);
}

You also get the error that's about to be posted as an argument in this function. The error is represented as an object with three properties: the error message, the line number and the script-source URL of the error. So, to ignore all errors that are from ad-script.js.

_errs.allow = function(err) {
  return (err.url.indexOf("ad-script.js") != -1);
}

On a side note, this indexOf and -1 business above is so ugly! String.prototype.contains can't come soon enough!

This was a fun feature to build, especially because of a very interesting corner-case. All of this has been well documented, so give the docs a look. It's very interesting how Errorception uses itself to log errors encountered in this edge-case in a way that doesn't cause the world to implode.

Monday, 13 January 2014

Country of Origin

Sometimes, when debugging client-side errors, knowing where the user is from can be useful. For example, I recently had a situation where I had debug an error that only occurred for users behind the Great Firewall of China. Granted these kinds of issues only crop up rarely, but at such times knowing that this error only occurs in certain geographical locations can be immensely useful when trying to debug.

Errorception now displays the country of origin of the error occurrence, whenever possible. Due the very nature of IP-address-based geo-location, the location accuracy can only be very coarse-grained, and might even be entirely wrong, but is right most of the time. Also, I only started collecting geo-data over the weekend, so older error occurrences will not have geo data tagged along with it.

Happy debugging!

Tuesday, 26 November 2013

HTTPS Everywhere

This has been a long time coming.

Errorception is now proudly 100% HTTPS. (Well, nearly 100% – read on.)

It turns out, migrating a site to HTTPS isn't as simple as it seems, especially if you have to do it right. I had a huge checklist to look at and verify for this launch. Here's what else has changed with this update:

  • Save for this blog and one route that currently needs to be HTTP, all URLs are now strictly only accessible over HTTPS. HTTP access has been disabled. As for that one route and this blog, they are over cookie-less subdomains, and don't carry any sensitive information.
  • Cookies are only set when using HTTPS, and have been marked as secure cookies. HTTP cookies that were set in the past are now meaningless. In fact, I've deleted the entire old session-store to ensure that there can be no session hijacking.
  • The encryption is end-to-end. In this case, it means that SSL doesn't just terminate at the load-balancer. The connections between the load-balancer and the app servers are also all SSL. Everything is encrypted. Take that, NSA!
  • Cookies will henceforth be inaccessible to client-side code to prevent a large class of XSS attacks.
  • There are several other security measures implemented. For example, Errorception now implements HTTP Strict Transport Security, prevents clickjacking where possible, reduces MIME-type security risks where possible, and has force-turned on XSS-filters to prevent reflected XSS attacks.
  • All external assets included in the site are now loaded over HTTPS as well, to prevent mixed-content scenarios. All links from communications like emails have been updated to use HTTPS URLs. Links that have been forged in the past will still work, but will be redirected to HTTPS.

Unfortunately, because cookies will have to be recreated over HTTPS and since the session store has been cleared to ensure that old cookies are invalid, it means that you will have to log in again to your Errorception account. It's a minor inconvenience, but it's a small price to pay for the vastly improved security.

I'm by no means a security expert, so if you find any lapses, please feel free to let me know. (I'm rakeshpai at errorception dot com.) Also, security is never really done, so I consider this as only the first step in getting to better security.

Wednesday, 20 November 2013

Why Throw When You Can Just Push?

I had previously launched a feature to .push your errors to Errorception if you liked. It also required you to throw your errors immediately after the push.

Turns out, many people don't like to throw their errors. There could be several reasons for not throwing your errors – for example, if you want to handle it gracefully, but still want it logged. Also, some frameworks such an Angular and Ember provide you with Error objects, but throwing them might not be what you want to do.

Now with Errorception, you don't need to throw error objects anymore. Simply .push them, and you are done!

I must hasten to add that I would consider this usage advanced. A throw, despite all its weirdness, is the best way to halt a problem immediately. If there's an error that you haven't anticipated, chances are you will want to stop your program's execution. If you are going to deal with errors properly, you don't need to throw them, but then you wouldn't have an error in the first place. This makes the feature only useful for a small set of cases. If you are not throwing your error, I hope you know what you are doing.

If your code was already throwing errors after pushing them, you won't have to change a thing. Don't worry – you won't get duplicate errors. In fact, this behaviour (push, with or without throw, without duplicates) will be supported forever, because of the reasons in the paragraph above.

Tuesday, 22 October 2013

Stack Traces, window.onerror, and the future

One argument that many people have made (and still make) is that window.onerror doesn't provide sufficient information to track down client-side JavaScript errors. While there's certainly some truth to it, I've always thought of it as a case of worse is better.

Consider the alternative: you'd have to wrap all your code in try/catch blocks. But that's not enough. Because of the nature of the event loop in browsers, you will also have to wrap all your async code in try/catch blocks as well. That includes all DOM event handlers, XHR and family including WebSockets, and setTimeout and family. That's something you'll just have to do. Because this requires modification of your code, it's terribly invasive. This also means that you will almost certainly miss catching errors in several cases, simply due to oversight. And that's still not saying anything about the performance overhead of working with try/catch blocks, not just in Chrome. All that, just to get some additional data.

Errorception lets you pass your error objects to us if you want to, since quite some time now. However, less than 10% of errors at Errorception are recorded using this method. It is obvious that the window.onerror approach works far better, either because try/catch isn't comprehensive, or because it is inconvenient to use.

window.onerror = function(message, fileName, lineno) { ... }

That's all the data you got from window.onerror: the error message, the URL of the script, and the line number. Errorception of course records much more information about the browser and its state for you automatically, so there's already a lot of context available.

But Errorception has sorely lacked a very vital piece of data to aid debugging: stack traces. Stack traces are trivial to extract from the error object you get in the catch block of a try/catch statement. Sure, there were a couple of tricks up our sleeve to get fake stack traces where possible, but those were severely limited.

Obviously this problem wasn't one that just Errorception faced. The web community went to browser vendors and standards bodies with their torches and pitchforks (ok, it wasn't quite as dramatic as that), to ask for some love for window.onerror. A couple of months ago, the HTML spec finally added two new attributes for window.onerror.

window.onerror = function(message, fileName, lineno, colno, error) { ... }

See that last argument there? That's what's exciting. That's the error object you would have otherwise got if you had wrapped your code in try/catch blocks. That's right: You don't need to wrap your code in try/catch blocks anymore to get rich error information. This changes everything!

Browser support

As of this writing, no production browser supports these new attributes. But don't let that dishearten you – the spec is only about 3 months old after all. IE10 does support the colno attribute, but not the error object itself. That's because IE10's release predates the spec. I expect the next release of IE to have the error object supported. (Seriously, let's cut IE some slack. They've been doing some rocking work lately. They certainly took the lead here.) Chrome already rolled this out in Chrome Canary two months ago, so it should be be in a public release soon. Discussions are on in Firefox's Bugzilla, and I expect this to be resolved soon as well. The folk over at WebKit seem interested too, though admittedly progress has been slow.

Errorception and window.onerror

Needless to say, Errorception has now rolled out support for the new attributes on window.onerror. Since Errorception already uses window.onerror to record errors, you literally don't need to change a thing (yes, even though the attributes are new). Errorception will record stack traces for your errors whenever available. In fact, I've already tested this with Chrome Canary, and it works like a charm! Yes, this works for Cross-Origin errors too!

This should finally lay to rest the argument about whether try/catch blocks are better for JavaScript error logging, or if one should use window.onerror instead. There's absolutely no advantage to using try/catch blocks for error logging anymore. It's still useful for handling exceptions, sure, but it isn't useful for logging. And if you are using Errorception, you are already using the best mechanism for error logging. Of course, you should be used to that by now. ;)

As always, if you have any questions or feedback, the comments are open.