Documentation

Source Maps

Documentation - Source Maps

When dealing with minified JavaScript the information supplied in stack traces does not provide accurate line/column information to track down the source of the error. To deal with this you can utilize a source map which will provide the translation between the original JavaScript source and the minified version.

Raygun supports source map decoding for the information supplied by browsers which produce a line and column number for error information. Typically any errors which are specifically raised by you will contain this information. Recent versions of Chrome will also produce this information for window.onError global errors.

What you need

Raygun requires the following to complete the decode process:

  • Valid line/column numbers to be present in at least one line of the stack trace
  • An accessible minified JavaScript file as specified in the stack trace. This is either downloaded or retrieved from the source map center to determine if there is map file present
  • The map file to be correctly indicated in the minified JavaScript file using a footer comment
  • An accessible source map file (either publicly hosted or uploaded to the source map center)
  • To provide inline code snippets we also require the sources content field of the map file to be present or for the map file to point to publicly accessible unminified source JavaScript files. If neither of these are provided decoding of line numbers and variable names can still succeed but no inline code will be displayed with the stack trace

Recommended minifier tooling

We recommend using UglifyJS2 to generate a source map file.

Both the minified JS and its map file should use relative pathing. Look into the -p and --source-map-root options.

Validate your Source Maps

Ensure that your source maps are compatible with Raygun by using our validation tool. We have created a handy tool that allows you to validate your source map files for use with Raygun..

Uploading JavaScript files

If you do not wish to have publicly accessible JavaScript files you can upload them directly to Raygun from the JS Source Map Center. This is within the Application Settings submenu on the main dashboard.

Within the Source Map Center you can upload files and label them with the URL they would normally be accessed from. When a JavaScript error is mapped we will use the files you uploaded instead of trying to access them from your servers.

In addition to the upload page we offer an API endpoint, the URL is displayed in the Source Map Center and is specific to each application.

Simply send a post request with "URL" and "file" parameters specified to upload the file. Any existing files with the same URL will be overwritten.

The request must be authenticated by adding either a basic auth header for a user with access to the application (eg. "Authorization: Basic MyBasicAuthToken") or an External Access Token appended as a querystring parameter (eg. "https://app.raygun.io/upload/jssymbols/MyAppId?authToken=MyExternalAuthToken").

External Access Tokens can be generated from your user settings page.

Here is a cURL example request using Basic Authorization:

curl
  -X POST 
  -u email@example.com:password 
  -F "url=http://example.com/myjs.min.js" 
  -F "file=@C:\website\js\myjs.min.js"  
  https://app.raygun.io/upload/jssymbols/MyAppId

Here is an example using the Grunt plugin grunt_http_upload using an External Access Token:

http_upload: {
  your_target: {
    options: {
      url: 'https://app.raygun.io/upload/jssymbols/MyAppId?authToken=MyExternalAuthToken',
      method: 'POST',
      data: {
        url: 'http://example.com/myjs.min.js'
      }
    },
    src: 'C:\website\js\myjs.min.js',
    dest: 'file'
  }
}

Private source maps setup example

To get started you will need a tool which can help produce a source map as part of producing a minified version of your JavaScript. We personally use UglifyJS and find it to be a great tool. To install it you will need Node.js installed, you can then run:

npm install uglify-js -g

This will install Uglify so that it's globally available which is what you will typically want.

To produce minified JavaScript we can simply run 

uglifyjs example.js -o example.min.js

To produce minified JavaScript with a mapping file we can run

uglifyjs example.js -o example.min.js --source-map example.min.js.map

This produces the minified file "example.min.js" as well as a source map file "example.min.js.map"

If you deploy the minifed file example.min.js to production but do not wish for any or some of these files to be publicly accessible you will need to upload these files to Raygun to get source mapped stacktraces.

You can do this from within Raygun by accessing the JS Source Map Center in the Application Settings sub menu.

Here you can simply select the minified, mapping and source files to upload. After uploading you can type the URL the resource is mapped to so when our source mapping process tries to retrieve the file, it uses the file you uploaded instead.

You can determine the URL to enter by looking at the map file's "file" and "sources" properties. You can then prepend the URL of the minified file on production minus the filename.

For instance, if we have a minified file example.min.js located at http://example.com/scipts/example.min.js and we upload example.min.js, example.js and example.min.js.map to Raygun. We would assign their URL's like this:

After the files are uploaded they will be used in the source mapping processes. This is what your mapped stacktrace will look like:

Using Private Source Maps for Hybrid Mobile Apps

With many mobile applications being written in JavaScript within containers such as Apache Cordova, using Raygun4js is an appealing way to track errors across all platforms. However as the application is hosted on the phone instead of a website with a static URL you may find that error stacktraces contain files paths which differ across different platforms and devices. This introduces some difficulty when trying to utilize source maps which require the minifed and mapping files to be uploaded and labeled with exactly the same URL's as would appear in a stacktrace.

For this reason we recommend adding a handler to the raygun4js provider to rewrite file's URLs before the error is reported back to Raygun. This means that errors will be reported from the same domains and not unique domains for every platform or device.

An example of such a handler is shown below:

//handler method
var beforeSend = function(payload) {
    var stacktrace = payload.Details.Error.StackTrace;

    var normalizeFilename = function(filename) {
        var indexOfJsRoot = filename.indexOf("js");
        return 'http://normalizedurl.com/' + filename.substring(indexOfJsRoot);
    }

    for(var i = 0 ; i < stacktrace.length; i++) {
        var stackline = stacktrace[i];
        stackline.FileName = normalizeFilename(stackline.FileName);
    }
    return payload;
}

//attaching the handler to the Raygun provider
Raygun.onBeforeSend(beforeSend);

This handler removes the platform and device specific paths from the URL's present in an error's stacktrace.

For instance an error occuring on an Android phone within the file

file://android_asset/www/js/myjsfile.min.js

and on an iOS device within the file

file://accounts/1234/appdata/b12b33f1-519b-4d1c-8d68-315513ecbac1/www/js/myjsfile.min.js

will both report

http://nomalizedurl.com/js/myjsfile.min.js

as the URL of the file within which the error occured.

This allows the use of a single set of sourcemaps for source mapping across all deployments.

Notes:

There could be up to a 30 minute delay before the mapping process starts utilizing any uploaded files. To reprocess any errors which occur during this time simply hit the "Re-process this error for Source Maps" button on an error instance.

Code snippet insertion is only available if there are less than 50 source files referenced in the map file.

Managing files in the JavaScript Source Map Center

Files in the JavaScript Source Map Center can be managed via a few API calls.

A GET request to https://app.raygun.io/jssymbols/[applicationIdentifier] will return a JSON object listing all files within the center. eg.

curl
  -X GET 
  -u my@email.com:mypassword 
  https://app.raygun.io/jssymbols/[applicationIdentifier]

Returns:

{ 
  "Count": totalNumberOfItems, 
  "Items": [
    {  
       "Url": "https://urlOfItem", 
       "FileName": "fileName.js", 
       "UploadedOn": "2016-01-01..." 
    },
    ...
  ] 
}

A DELETE request to https://app.raygun.io/jssymbols/[applicationIdentifier]/all will remove all files within the center. eg.

curl
  -X DELETE 
  -u my@email.com:mypassword 
  https://app.raygun.io/jssymbols/[applicationIdentifier]/all

A DELETE request to https://app.raygun.io/jssymbols/[applicationIdentifier] will remove files with the specified URLS from the center. eg.

curl 
  -X DELETE 
  -u my@email.com:mypassword 
  -F "url=https://example.com/js/myjs.min.map"
  https://app.raygun.io/jssymbols/[applicationIdentifier]

All requests use the same authentication methods as the upload call (Basic Authentication and Token Authentication).

Documentation missing?

If we don't have documentation about your desired topic, send us a message and we'll create it for you.