Web performance integration guide

Step-by-step instructions for adding performance monitoring to your web projects.

The BugSnag Performance web integration is a JavaScript library that runs in the browser and automatically instruments full page loads (including Core Web Vitals), route changes, resource loads and fetch/XHR network requests. This allows you to get a full picture of your users’ experience.

Your JavaScript code can also be manually instrumented to gather your own performance measurements.

New to BugSnag? Create an account

Looking for error monitoring? See our integration guides

Installation

NPM

If you use npm or yarn in your project, install the @bugsnag/browser-performance package:

npm install --save '@bugsnag/browser-performance'
# or
yarn add '@bugsnag/browser-performance'

CDN

Alternatively you can simply include the BugSnag Performance package as a script directly from our CDN:

<script type="module">
  import BugsnagPerformance from '//d2wy8f7a9ursnm.cloudfront.net/v2.10.0/bugsnag-performance.min.js'
</script>
Selecting a version from the CDN

Each release is versioned according to semver. You can tweak the exact URL depending on whether you want to lock to a specific version or accept minor or patch updates automatically:

<script src="//d2wy8f7a9ursnm.cloudfront.net/v2.10.0/bugsnag-performance.min.js"></script>
<script src="//d2wy8f7a9ursnm.cloudfront.net/v2.10/bugsnag-performance.min.js"></script>
<script src="//d2wy8f7a9ursnm.cloudfront.net/v2/bugsnag-performance.min.js"></script>

Further advice and guidance can be found in the CDN guide for our Error Monitoring SDK.

The latest available version of @bugsnag/browser-performance is v2.10.0.

Basic configuration

Depending on which module system you are using, you’ll need to include BugSnag in one of the following ways:

// commonjs/node-style require
var BugsnagPerformance = require('@bugsnag/browser-performance')

// ES module-style import
import BugsnagPerformance from '@bugsnag/browser-performance'

// CDN import
import BugsnagPerformance from '//d2wy8f7a9ursnm.cloudfront.net/v2.10.0/bugsnag-performance.min.js'

Then start sending performance data by providing your API key as a string:

BugsnagPerformance.start('YOUR_API_KEY')

This is the same API key used by the BugSnag Error Monitoring library.

You can find your API key in Project Settings from your BugSnag dashboard.

We recommend you also set your app’s version and the release stage of the build so that performance data can be easily filtered on the BugSnag dashboard. This is done by passing a configuration object when you start the library:

BugsnagPerformance.start({
  apiKey: 'YOUR_API_KEY',
  appVersion: '4.10.0',
  releaseStage: 'testing'
})

See Configuration options for details on the options available.

Instrumenting page loads

BugSnag will automatically detect and report metrics when a page loads. These timings are shown under the “Page loads” tab in the BugSnag Performance dashboard. Page loads are split into full page loads and route changes: the latter are generated on single-page apps (SPAs) where the page is not actually reloaded but the app redraws to a new logical page.

We measure the period of time it takes to load either type of page, using a heuristic we have implemented to detect when a page has “settled”. For more information on this algorithm, see details here.

Web vitals

During a full page load we also capture various metrics that describe the details of how the page loaded. These are called Web Vitals (see Web Vitals for more details) and are presented in your BugSnag dashboard for analysis.

Route names and router integrations

If your app has parameterized page URLs, you should group all measurements on your BugSnag dashboard by the page template, or “route”, rather than specific URL on which it was captured. For example, rather than capture /account/john.smith/orders you would want the dashboard to show /account/:username/orders.

If you use the following popular libraries, we have packages that do this automatically by integrating with their routing configuration and event hooks:

Alternatively this can be achieved by implementing a function in your BugSnag configuration that maps a URL to a generic route name that makes sense for your app. Please see our Customizing routes guide for information on tailoring route names to your app, as well as adjusting the start and end period of these measurements if required.

Further configuration

To disable automatic instrumentation, set the autoInstrumentFullPageLoads or autoInstrumentRouteChanges configuration options:

BugsnagPerformance.start({
  apiKey: 'YOUR_API_KEY',
  autoInstrumentFullPageLoads: false,
  autoInstrumentRouteChanges: false
})

You can restrict which network requests count towards the page settling measurement using the settleIgnoreUrls configuration option.

Instrumenting network requests

BugSnag will automatically detect and report XMLHttpRequest (XHR) and fetch network requests made by your web app. These timings are shown under the “Network requests” tab in the BugSnag Performance dashboard.

The networkRequestCallback configuration option allows you to control the data sent in these network request spans using a callback.

To disable the capture of these requests, use the autoInstrumentNetworkRequests configuration option:

BugsnagPerformance.start({
  apiKey: 'YOUR_API_KEY',
  autoInstrumentNetworkRequests: false
})

You can instrument network requests manually by calling BugsnagPerformance.startNetworkSpan when a request is started and end on the resulting Span on completion:

const span = BugsnagPerformance.startNetworkSpan(
  { method: 'GET', url: 'https://example.com/api' })

// When the network request has completed:
span.end()

Sending custom spans

To send custom spans to BugSnag for any other operations you wish to measure, use BugsnagPerformance.startSpan to start a span, and call the span’s end method to end the measurement:

let span = BugsnagPerformance.startSpan('login')
await LoginApi.login()
span.end()

The spanOptions parameter allows you to customize some elements of the span’s behavior:

Reporting child-only spans

If a custom span is “first class”, its performance characteristics will be aggregated and shown in the “Custom” tab of the BugSnag dashboard. If the custom span is useful only for adding insight into the performance of its parent (through the waterfall diagram on the span instance page), you should set the isFirstClass span option to false:

BugsnagPerformance.startSpan('always-nested', { isFirstClass: false });

Controlling span hierarchies

When viewing a single instance of a span in the BugSnag dashboard, a waterfall diagram will show you that instance’s children and their children, and so on. This allows you to see in more detail where the time was spent, and aid diagnosing and fixing any problems. When creating your own spans, you can use the options parameter to control their parent-child relationships to produce a meaningfully representative hierarchy in your dashboard. See Maintaining span context for more information.

Start and end time overrides

By default, a span will use the current timestamp as its start time. However, you can use the startTime span option to report spans that have already started by providing your own timestamp. You can also end a span with your own timestamp to provide a retrospective end time.

Note that the values you provide must either be Dates, or numbers relative to performance.now(). The number produced by Date.now() will not have the desired effect.

let taskStartTime = new Date()

// When the task has completed:
let taskEndTime = new Date()

BugsnagPerformance.startSpan('retrospective-span', { startTime: taskStartTime })
  .end(taskEndTime)

Adding custom span attributes

Additional data can be added to spans to help diagnose performance issues. These are sent as span attributes and will be displayed on your Performance dashboard alongside the automatic span data captured by the SDK.

Screenshot of custom attributes panel

Attributes are added via a span object and are name value pairs where the type can be either a string, integer, double, boolean or an array of one of these types:

const span = BugsnagPerformance.startSpan('span-with-data')
span.setAttribute('api.protocol', 'gql')
span.setAttribute('api.version', 'v2')
span.end()

You can use a callback to set attributes when they are ending. This allows you to access all spans being generated, including those from automatic instrumentation:

BugsnagPerformance.start({
  apiKey: 'YOUR_API_KEY',
  onSpanEnd: [(span) => {
    span.setAttribute('device.locale', 'en-US')
    return true
  }]
})

The number and size of attributes added to spans are limited by the SDK to avoid oversized span payloads that would be rejected by the BugSnag API. See the Custom attribute limit configuration options to see how this can be customized if more data is required.

These callbacks can be executed with a high frequency, so care should be taken not to perform complex operations that will have a detrimental effect on performance. For more information, see the span callbacks configuration option.