Technology for Dogs

JavaScript Error Reporting Using Source Maps and Sentry in Django

Sure, you have error reporting for when your app 500’s, but do you know when your latest JavaScript changes to your core funnel interactions block your users from doing anything at all? Errors are far easier to catch and test for on the backend using automated unit tests, but the front-end of the web is everything but predictable. You can test to your heart’s content with qUnit or Jasmine, and automate your testing in tools like Browserstack and DalekJS, but even our best efforts will have bugs falling through the cracks.

JavaScript error reporting

At Rover, we use Sentry for all of our application error logging. It has a great Django logging handler that allows us to funnel any and all uncaught errors directly into Sentry, which aggregates the errors, captures the details, and notifies our dev team. When we saw that Sentry supported JavaScript logging as well, we were sold. There was only one problem: because we compress and minify all of our JavaScript using django-compressor, all the errors would be on line 1 of b00222c8b879.js…not very helpful.

Source maps

Source maps, for the uninitiated, are a means of mapping a compressed file back to its original source file and line number. During the compression step, you tell your compressor to generate a .map.js file in addition to the compressed file. While the source map spec is still sitting in a Google Doc (for real), the spec has been implemented by various parties (Mozilla, Google) and is usable today. Not only is this useful in error reporting, but you can also use source maps for debugging compressed source code on your production site! Chrome will auto-detect the map files in your compressed source and grab the original files, allowing you to set breakpoints inside compressed files while they are in the wild.

django-compressor-sourcemaps

Uglifyjs supports source maps out of the box, but we needed to add the ability for django-compressor to ask uglifyjs to generate those source maps for us. To do this, we wrote django-compressor-sourcemaps. It allows any user of django-compressor to tweak a couple settings variables and have source maps working straight away. Since we feel the entire Django community could benefit from a greater ability to debug JavaScript errors in production, we’ve open-sourced this component at django-compressor-sourcemaps – contributions welcome!

Setup

  • Install the prerequisites on your machine doing the compressing:

  • Grab uglify.py from our django-compressor-sourcemaps repository and toss it in your application. We house it inside our common Django app.

  • Change your settings variables to use the JsUglifySourcemapCompressor as the JavaScript Compressor.

1
COMPRESS_JS_COMPRESSOR = 'common.uglify.JsUglifySourcemapCompressor'
  • If you’d like to enable Sentry reporting for JavaScript errors, follow their documentation.

Gotchyas

While implementing this, we ran into one main issue that gave us some trouble. We had a few blocks of JavaScript that were in templates, not inside JavaScript files, but were in compress blocks. Since uglifyjs can only compress files (and not inline JS blocks), we needed to refactor those blocks out into files (where they should have been in the first place).

Hit me up at @croby with any comments or questions!