Source Maps to the rescue.!
So you’ve set up Sentry for you javascript project & released it to production, excited about the first error that’ll come up & you got this!
Uh oh, so “name of undefined”, oh I know, an
If check
is all I need.where again? — In:
chatModule-322816772254.js in h.e.uploadFile at line 1:27468.
Wait, where’s that? — Darn!
That’s exactly what source maps help you fix, to map this error location to the line of code you typed before it became a mess while shipping to the client.
Sentry provides multiple approaches from where it can read source maps:
Hosting your source maps seems like the easiest task but it also exposes your un-minified code to the public, making it easier to find security loopholes. One way to tackle this is to set up a VPN so these are not accessible anywhere else other than your company.
Since we want the freedom to be able to read those sentry errors from anywhere, we’ll discuss the latter approach here.
The articles originate from the problems I faced when trying to upload source maps to sentry & how I made it work in the end.
This step will vary based on your build system. If you’re using browserify, gulp, uglify, here’s how you should do it:
debug:true
in your browserify optionsgulp-sourcemaps
& initialise the same before minifying the codeFinal code might look something like:
var sourcemaps = require('gulp-sourcemaps');
browserify(path, {
paths: ['./node_modules'],
// Enables source maps
debug: true,
})
// Any babel config may come here
// ---
// Initialises & writes source maps
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(uglify())
.pipe(sourcemaps.write('.'))
// Used to export generated minified files & source maps
.pipe(gulp.dest('./web/js'));
At this point we have our minified files & source maps generated in the
/web/js
folder like /web/js/file.min.js
& /web/js/file.js
which are hosted as https://{your_domain}/js/file.min.js
& https://{your_domain}/js/file.js
respectively.Here’s a script which uses
sentry-cli
to upload the javascript files from a folder to sentry & remove the source maps files post that:// Credit: https://github.com/supriya-raj
var spawn = require('child_process').spawnSync;
var sentryHost, sentryAuthToken, sentryProjectName, sentryOrg, release;
/*
Change based on your requirement:
sourceMapsPath: relative path to the folder that contains your minified scripts & source maps
jsUrlPrefix: ~ (tilde) -> Acts as your domain. Ex: if the source maps are hosted on domain.com/js/file.js.map
this should be '~/js'
release: source maps will be pushed under this release name
sentryConfig: {
org: 'dummyorg'
project: 'my-js-project'
host: 'https://sentry9.dummyorg.com'
auth_token: ~
}
^ Example configuration for the sentry url: https://sentry9.dummyorg.com/dummyorg/my-js-project
*/
var sourceMapsPath = 'web/js';
var jsUrlPrefix = '~/js';
var sentryConfig = require('./sentry-config.js')
if(sentryConfig) {
sentryHost = sentryConfig['host'];
sentryProjectName = sentryConfig['project'];
sentryOrg = sentryConfig['org'];
sentryAuthToken = sentryConfig['auth_token'];
}
release = process.env.COMMIT_HASH;
if (!sentryAuthToken || !sentryHost || !sentryProjectName || !sentryOrg) {
console.log(console.log('[Error] One or more config parameters required for source map upload are missing!'));
process.exit(1);
}
if (!release) {
console.log(console.log('[Error] Environment variable COMMIT_HASH does not exist!'));
process.exit(1);
}
spawn(
'./node_modules/.bin/sentry-cli',
[
'--auth-token', sentryAuthToken, '--url', sentryHost, 'releases',
'--org', sentryOrg, '--project', sentryProjectName,
'files', release, 'upload-sourcemaps', sourceMapsPath,
'--url-prefix', jsUrlPrefix, "--no-sourcemap-reference"
],
{stdio: "inherit"}
);
spawn(
'find',
[sourceMapsPath, '-type' ,'f', '-iname', '\*.js.map', '-delete'],
{stdio: "inherit"}
);
Auth token can be generated by:
Sentry Project -> Settings -> Search (Auth Tokens) -> Create new token
For the above project, we’re using the latest commit hash to mark release tag so, that needs to be passed as an environment variable before executing the provided script:
COMMIT_HASH=${COMMIT_HASH} node ./upload-source-maps-to-sentry.js
Verify the source maps in Sentry should now be available under:
Project -> Releases -> {Commit_Hash} -> Artifacts
At this point, the source maps are pushed to sentry but for a particular issue, sentry doesn’t know where to find them to un-minify & give you those pretty errors.
To achieve that, send a
release
attribute along with the sentry init configuration, Here’s a sample config for @Sentry/browser 5.7.1
window.Sentry.init({
dsn: '<sentry_dsn>',
release: '<COMMIT_HASH>',
})
& Voila! There you have it, the same error but this time identifiable 👁, thanks to source maps.
Here’s a good resource to detect what might have gone wrong with your implementation.