Monday, 20 May 2013

Better Script Delivery

I'm in the process of switching CDNs from Amazon's CloudFront to CloudFlare. While CloudFront has been generally good, it fell short in a couple of ways. So far, CloudFlare solves all of these problems and then gives the opportunity to have even more interesting possibilities.

There were two major problems with CloudFront:

  • No CNAME support. Not for HTTPS, at least. As a result, I've had to give you a script with a someuglytoken.cloudfront.net URL in it. But the problem is beyond just ugliness. It gives me no control to change CDNs in the future. I've been living with this so far, but it's far from ideal. CloudFlare solves this problem elegantly.
  • It's a dumb CDN. Like, really dumb. It doesn't do any content-negotiation for what I'd consider even the most basic things. For example, if you want your scripts to be gzipped, you'd have to upload pre-gizpped scripts to the CloudFront. If a browser comes along that doesn't understand gzip, it's out of luck.

The second issue might seem obvious and trivial, but has its consequences. For example, PageSpeed recommends that every asset on the page should have a Vary: Accept-Encoding header. However, on CloudFront if I provide a Vary header, I'd be lying to the network, because I'm not able to vary the content at all. As a result, all sites that had embedded Errorception's snippet would have seen a slight reduction in their PageSpeed score. Indeed, there have been requests to fix this.

Not only do the two problems above get fixed by the move to CloudFlare, it allows for very interesting possibilites in the future. Since CloudFlare is much more smart as compared to CloudFront, and since it effectively works as a caching-proxy, the possibilities are limitless! There are features I simply couldn't roll out on CloudFront which become trivial to do on CloudFlare.

Action needed

Unfortunately, this change requires you to change the script snippet that you've embedded on your site. I know it's a pain to have to do this. I apologize. The last time I asked you to do this was over a year and a half ago, so I assure you that these kinds of changes don't happen frequently. Please go to your Settings > Tracking snippet to get the new snippet.

Upgrade plan

The current script on Amazon's CloudFront will be supported for a couple of months more. Over this period, if there are any critical bugs, I'll be making releases to both the CloudFront and CloudFlare CDNs. Feature releases will not be rolled out to CloudFront, so you will not get any new features if you are using the old snippet. It's highly recommended that you upgrade as soon as possible to ensure that you have the very latest features.

Monday, 29 April 2013

Get your JS error notifications wherever you like!

Just three days ago, I had launched WebHooks support so that you can view your site's client-side JS errors anywhere you prefer. The trouble with vanilla WebHooks is that everyone has to implement the same sets of hooks for integration with the same services. For example, if two companies need the error to be posted to HipChat, they'd both have to independently develop HipChat integrations on top of Errorception's WebHooks, and then manage and maintain their implementations themselves. Such a pain! So, today, there are two announcements to help ease the pain.

Firstly, using the same underlying stack I'm using for WebHooks, I'll host integrations for most popular services myself so that you don't have do a thing. I'm calling this service hooks, blatantly copying the name from GitHub. Simply go over to your settings, and click on Service Hooks to find the list of services you can already integrate with today. You don't have to write any code to implement the hook. Just fill a form, and you are ready to go.

Currently, I'm launching Campfire, HipChat and PagerDuty integration. Integrations with these services have been asked for before, so I decided to start with these. I expect this list to expand further.

   

What an error looks like on Campfire (left) and HipChat

As interesting as that is, what's even more exciting is how it's implemented, and how it matters to you.

<3 GitHub, <3 open-source

All the code that makes these service hooks possible is all open-source. Check it out on GitHub. Even the documentation on Errorception for these services is driven off README.md files from GitHub! That's just awesome!

There are two reasons I wanted this to be open-source. One of the reasons of course is that I like the transparency with open source. When I'm asking you to enter API tokens for, say, your HipChat account, I want to make it clear to you that I'm not going to misuse it. What better way to convince you than to show you the code itself!

Secondly, and probably more importantly, if you want to see a new service integrated with Errorception, you will be able to do that yourself! Just fork the repo on GitHub, write a small little JS function to implement the integration, and send me a pull request. I'll have it merged in no time, and will immediately be available to everyone. It's really simple! And when I say it's a small little function, I mean it - Have a look at the WebHooks implementation as an example.

I've had a lot of fun planning and coding this release. I hope you make the most of it. And if you want to see your favorite services integrated with Errorception, feel free to give it a shot on GitHub. I'll only be glad to help you along.

Friday, 26 April 2013

Announcing WebHooks

Though the Errorception HTTP API is awesome for browsing your errors, it has so far been very hard to get real-time error notifications. There was the hacky solution of polling the API of course, but that's terribly inefficient, and just feels dirty. Today, this gets fixed.

You can now configure WebHooks in your settings, which Errorception will POST to whenever it encounters an error on your site. You can choose if you want to receive POSTs for every occurrence of every error, of the very first time an error occurs.

This has been made available to all projects in Errorception, just like every other feature. Head over to the WebHook docs to learn how to make the most of this feature.

As usual, feedback always welcome! I can't wait to see what you'll be pulling off with this. :)

Tuesday, 19 February 2013

Error Object Compatibility Table

I've been spending some time lately studying JavaScript's Error object. These are some of my notes on Error object compatibility across browsers, in case anyone else finds this useful.

Property Google Chrome Safari Opera Firefox MSIE
name Yes Yes Yes Yes Yes
message Yes Yes Yes Yes Yes
stack Yes Yes Yes Yes Yes (IE10+)
toString() Yes Yes Yes Yes Yes
type Yes No No No No
columnNumber No No No Yes No
fileName No No No Yes No
sourceURL No Yes No No No
line No Yes No No No
lineNumber No No No Yes No
number No No No No Yes

Notes:

  • Though file name is available in the .stack property, only Firefox and Safari provide this as an explicit property, and that too with different property names (FF: .fileName, Safari: .sourceURL).
  • All browsers string-format the stack subtly differently. There's no standard regarding stack formatting. Firefox has the least informative stack property. I'm going to cut Firefox some slack though, since they were the first to expose this property. That said, this might change in the future. Worth keeping an eye on this discussion.
  • Firefox doesn't provide column numbers in the stack at all. However, it does provide a .columnNumber property which is only useful for the first stack frame.
  • The .number property (IE) is practically useless. It points to IE's internal representation of errors.
  • .line (Safari) and .lineNumber (Firefox) properties give the line number of the first stack frame of the error. No one else provides a similar property, though this data is available in the .stack everywhere except Firefox.
  • The .toString() formatting seems consistent, and similar to the formatting of the error message in window.onerror. That is, it uses the format name + ": " + message. The only exception to this, of course, is that window.onerror formats errors differently when the source file has x-domain restrictions.
  • Column numbers in the .stack property are only available in IE10+ and Chrome. Opera provides a .stacktrace property in addition to .stack that has column numbers (go figure!). No other browser provides column numbers in the stack trace. As mentioned above, Firefox does provide an explicit .columnNumber property that's only useful for the first stack frame.
  • No stack support for IE<10. Nothing. Zilch.

Thursday, 31 January 2013

Stack Traces and Error Objects

A frequently requested feature has been that of stack traces with errors. However, because window.onerror, doesn't give access to an error object, it has not been possible for Errorception to capture stack traces. That's set to change today.

Starting today, you will be able to pass error objects to Errorception. An example is probably the best way to explain this.

try {
    var myObject = JSON.parse(jsonString); // will break if jsonString is invalid
} catch(e) {
    _errs.push(e);
    throw e;
}

When you pass such errors manually to Errorception, Errorception will now be able to record the stack trace for this error. Undoubtedly, this can be very useful for debugging.

Important

  • What you push to _errs should be a valid Error object, that is, it should be an instanceof Error.
  • It is important that you throw the error right after passing it to _errs. This is for two reasons. Firstly, you really want your program's execution to stop when you encounter an error, and throw is a great way to do so. Secondly, Errorception internally uses both the Error object and the data from window.onerror to capture error data. If you don't throw the error, Errorception will ignore the error object.

As an additional bonus, with the exception of Firefox and Safari, you will also get the column number of your error. This is especially important since your JS is likely minified without line-breaks. This column number information is especially exciting — it's likely to guide the future features of Errorception.

Bonus: This works perfectly well with the recently launched ability to record custom information with errors. For example, in Errorception I was recently doing this (yes, Errorception uses Errorception):

try {
    var myObject = JSON.parse(jsonString);
} catch(e) {
    _errs.meta = {json: jsonString};
    _errs.push(e);
    throw e;
}

Friday, 11 January 2013

Your JS Errors Are Now An API Call Away

It always annoys me when data gets caught in inaccessible silos, yet that's exactly what I had ended up building with Errorception. Today, that gets rectified.

Today I'm announcing the first cut of the Errorception API. As far as I know at least, it is the first API in the wild tailored specifically for JS errors in your site.

Being a huge fan of simplicity, the API is really simple to use too. In fact, I've embedded a curl example right here in this blog post:

$ curl -i https://api.errorception.com/
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 77
Connection: keep-alive

{"links":[{"rel":"projects","href":"https://api.errorception.com/projects"}]}

You can view detailed API documentation on the API docs page.

I'm excited to see what you will do with this data. I'm hoping to evolve this API based on what your experience is like. As usual, feel free to mail me at rakeshpai at errorception dot com with any suggestions or feedback.

Sunday, 6 January 2013

Improving Daily Emails

The daily notification email, which had been turned off for some time now due to a snag, has now been turned back on.

Previously, all the emails used to be sent at the turn of the day on the server. This was problematic in at least two ways.

  • The load on the DB to sift through the large volume of errors to generate emails was turning out to be a bit much. The server had begun to protest about the load.
  • All users got emails at the same time, irrespective of which timezone they belonged to. I would personally prefer to get my error notification in the morning when I'm starting my day, so that I can schedule time for fixing it. A mail that lands up in my mailbox when I'm about to go to bed is useless at best, and worrisome at worst.

Turns out, solving the latter problem solved the former problem as well, because the server load of sending out the email would get more-or-less evenly distributed across the entire day. So, taking inspiration from what Stride did recently, I've rolled out something similar for Errorception.

A small JS snippet notes your timezone every time you use Errorception. This timezone information is passed along to the server and recorded against your records. A cron kicks in every half hour on the server to determine if you should be sent an email to right now, based on whether it is 9:30 AM in your timezone, using the excellent 'time' module by Nathan Rajlich (TooTallNate). It just works!

So, starting about 15 mins ago, you should now receive emails at 9:30 in the morning, irrespective of which timezone you are in, or whether it's daylight savings or not. If you still aren't receiving emails, get in touch at rakeshpai at errorception dot com.

Almost forgot: Wish you a great 2013! Happy debugging!