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.

Monday, 14 October 2013

Say Hello To CORS

Errorception now uses CORS when available to send errors from the browser to the server. This makes the error POSTing process much more lightweight.

This wasn't the case so far. Error information was encoded into form fields and posted into a hidden iframe. While this largely worked fine, it wasn't without its problems. Serialising data as form fields isn't a big deal, even if slightly wordy. However, iframes are very resource-heavy, and are fraught with performance problems. Also, iframes are essentially just regular page loads, so they fire up the browser's loading indicators in the browser tab and show that little message in the status bar of the browser. All of this happens simultaneously. Obviously, users don't like this.

However, two years ago when Errorception was launched, JSON and CORS wasn't as ubiquitous as it is today. Forms and iframes, despite their problems, were the only workable solution, especially if like me you insist on using POST for posting data. Fast-forward to today, and the world is a different place. JSON and CORS are available in every browser worth their salt.

After weeks of development and extensive testing, I've released a new version of the tracking code to make use of JSON and CORS where possible, to ensure that your users see the least amount of performance degradation at any time. If CORS (or Microsoft's XDomainRequest) isn't available, the code falls back to working as it always has - with form fields and iframes.

Upgrade if you haven't already! This new code is only released to people who are using the latest tracking snippet. The new tracking snippet was released earlier this year, and already implements tons of performance improvements over the old one. You should upgrade if you haven't already. If you signed up after May, you are already on the latest code. If you've upgraded already, you rock!

Tuesday, 2 July 2013

IE's i18n Strings for Error Messages

After the release last week, there have been some requests to both Raj and me to have access to the raw data used for powering the IE i18n de-duplication, from several people, including from some of my competitors.

After a little bit of email back-and-forth with Raj, and ensuring that we were both ok with making this data available publicly, I'm glad to to have just pushed all the raw data to GitHub. Go ahead, give it a look!

What? You are giving data to your competitors?

Well, firstly, it isn't my data at all. It wasn't even extracted by me. Secondly, this isn't the kind of stuff I want to compete on. Data like this should ideally belong to everyone, so that the entire community benefits from it. This data being locked into any one service is doing disservice to the community at large. In fact, when I started this conversation with Raj, my original intention was to get MicroSoft to publish these resource files publicly so that everyone could benefit from it.

Cheers!