Source Maps

edit

It is a common practice to minify JavaScript bundles. However, debugging minified files is inherently difficult. To resolve this issue, you can generate source maps for your bundles and upload them to the APM server.

Here is an example to generate source maps with webpack and configure the JavaScript agent accordingly. For a detailed description of APM Server source map endpoint see our documentation.

First you need to configure webpack to generate source map and provide the service version to your app:

var webpack = require('webpack')
var serviceVersion = require("./package.json").version
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
  entry: 'app.js',
  output: {
    filename: 'app.min.js',
    path: './dist'
  },
  devtool: 'source-map',
  plugins: [
    new webpack.DefinePlugin({'serviceVersion': JSON.stringify(serviceVersion)}),
    new UglifyJSPlugin({
      sourceMap: true
    })
  ]
}

Or you can use current git commit hash:

var webpack = require('webpack')
var git = require('git-rev-sync')
var serviceVersion = git.short()
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
  entry: 'app.js',
  output: {
    filename: 'app.min.js',
    path: './dist'
  },
  devtool: 'source-map',
  plugins: [
    new webpack.DefinePlugin({'serviceVersion': JSON.stringify(serviceVersion)}),
    new UglifyJSPlugin({
      sourceMap: true
    })
  ]
}

Then you can use the provided service version to set the "serviceVersion" configuration:

import { init as initApm } from 'elastic-apm-js-base'
var apm = initApm({
  // Set required service name
  serviceName: 'service-name',

  // Set service version (required for source map feature)
  serviceVersion: serviceVersion
})

Make sure to upload the generated source map file to APM server with the same "serviceVersion" and "serviceName".

Here is a Node.js example of uploading source map file to the APM server:

console.log('Uploading sourcemaps!')
var request = require('request')
var filepath = './dist/app.min.js.map'
var formData = {
  sourcemap: fs.createReadStream(filepath),
  service_version: require("./package.json").version, // Or use 'git-rev-sync' for git commit hash
  bundle_filepath: 'http://localhost/app.min.js',
  service_name: 'service-name'
}
request.post({url: 'http://localhost:8200/v1/rum/sourcemaps',formData: formData}, function (err, resp, body) {
  if (err) {
    console.log('Error while uploading sourcemaps!', err)
  } else {
    console.log('Sourcemaps uploaded!')
  }
})

You can also use curl command:

SERVICEVERSION=`node -e "console.log(require('./package.json').version);"` && \
curl http://localhost:8200/v1/rum/sourcemaps -X POST \
    -F sourcemap=@./dist/app.min.js.map \
    -F service_version="$SERVICEVERSION" \
    -F bundle_filepath="http://localhost/app.min.js" \
    -F service_name="service-name"

Or use current git commit hash:

SERVICEVERSION=`git rev-parse --short HEAD` && \
curl http://localhost:8200/v1/rum/sourcemaps -X POST \
    -F sourcemap=@./dist/app.min.js.map \
    -F service_version="$SERVICEVERSION" \
    -F bundle_filepath="http://localhost/app.min.js" \
    -F service_name="service-name"

Using a secret token

edit

You can configure a secret token on APM Server to restrict uploading sourcemaps.

Here’s how to add the secret token to a curl command:

SERVICEVERSION=`git rev-parse --short HEAD` && \
curl http://localhost:8200/v1/rum/sourcemaps -X POST \
    -F sourcemap=@./dist/app.min.js.map \
    -F service_version="$SERVICEVERSION" \
    -F bundle_filepath="http://localhost/app.min.js" \
    -F service_name="service-name" \
    -H "Authorization: Bearer <token>"