BugSnag is now Insight Hub – we're making some changes to how the product looks, but this won't impact the way you use BugSnag or any of your integrations.

Named span access

Use SDK plugins to track open spans and access them by name from different parts of your codebase.

When starting custom spans, a reference to the object representing that span is returned and can be used to set further attributes or end the measurement.

const span = BugsnagPerformance.startSpan("login")

However, sometimes you may wish to end the span in a separate component, requiring an awkward passing of the object between scopes. The @bugsnag/plugin-named-spans plugin keeps track of all open spans and allows you to obtain a reference to them using just their name from anywhere in your codebase.

const span: Span | null = BugsnagPerformance.getSpanControls(new NamedSpanQuery('login'))
if (span) {
  span.setAttribute('user.id', 12345)
  span.end()
}

As well as JavaScript span access (see next section for details), you can also access native Android and iOS spans created with the BugSnag Android and Cocoa SDKs using the @bugsnag/plugin-react-native-span-access plugin. This allows you to track events that start in native code and end in JavaScript. See the Native span access section for details.

JavaScript span access

For access to spans created in JavaScript from elsewhere in your JavaScript code:

Installation

Install the @bugsnag/plugin-named-spans package:

yarn add @bugsnag/plugin-named-spans
# or
npm install --save @bugsnag/plugin-named-spans

Configuration

To enable the plugin, include it in the configuration options when starting the SDK:

import { BugsnagNamedSpansPlugin } from '@bugsnag/plugin-named-spans'

BugsnagPerformance.start({
  apiKey: 'YOUR_API_KEY',
  plugins: [new BugsnagNamedSpansPlugin()]
})

Usage

The plugin maintains a map of open spans that can be queried via BugsnagPerformance.getSpanControls(). The NamedSpanQuery class allows you to specify the name of the JavaScript span you want to retrieve.

import { NamedSpanQuery } from '@bugsnag/plugin-named-spans'

const span: Span | null = BugsnagPerformance.getSpanControls(new NamedSpanQuery('login'))
if (span) {
  span.setAttribute('user.id', 12345)
  span.end()
}

If the span does not exist; has already ended; or is no longer valid, it will return null. If multiple spans with the same name are open, only the most recent one will be returned.

To avoid memory leaks caused by spans not being ended, spans older than 10 minutes are removed from tracked memory to allow them to be deallocated.

Native span access

For access to spans created in native Android and iOS code from your JavaScript code:

Installation

Install the @bugsnag/plugin-react-native-span-access package:

JavaScript

yarn add @bugsnag/plugin-react-native-span-access
# or
npm install --save @bugsnag/plugin-react-native-span-access

Android

Add the following dependencies to your Module Gradle Settings, usually found at <project_dir>/android/app/build.gradle or build.gradle.kts:

dependencies {
    // ...
    implementation project(':@bugsnag_plugin-react-native-span-access')
}
dependencies {
    // ...
    implementation(project(":@bugsnag_plugin-react-native-span-access"))
}

iOS

run pod install in your iOS project directory to ensure the plugin is linked correctly:

npx pod-install

Configuration

Cross-layer tracking requires that the Native integration is installed and configured in your app.

To allow the React Native Performance SDK to access and manipulate native spans, add BugsnagNativeSpansPlugin to the native SDK configuration:

Android

import com.bugsnag.reactnative.performance.remotespans.BugsnagNativeSpansPlugin;

PerformanceConfiguration config = PerformanceConfiguration.load(this);
config.addPlugin(new BugsnagNativeSpansPlugin());
BugsnagPerformance.start(config);
import com.bugsnag.reactnative.performance.remotespans.BugsnagNativeSpansPlugin

BugsnagPerformance.start(PerformanceConfiguration.load(this).apply {
  addPlugin(BugsnagNativeSpansPlugin())
})

iOS

BugsnagPerformanceConfiguration *config = [BugsnagPerformanceConfiguration loadConfig];
[config addPlugin:[BugsnagNativeSpansPlugin new]];
[BugsnagPerformance startWithConfiguration:config];
let config = BugsnagPerformanceConfiguration.loadConfig()
config.add(BugsnagNativeSpansPlugin())
BugsnagPerformance.start(configuration: config)

JavaScript

To enable the plugin, include it in the configuration options when attaching to the native SDK:

import BugsnagPerformance from '@bugsnag/react-native-performance'
import { BugsnagNativeSpansPlugin } from '@bugsnag/plugin-react-native-span-access'

BugsnagPerformance.attach({
  plugins: [new BugsnagNativeSpansPlugin()]
})

Usage

The plugin maintains a map of open native spans that can be queried by name via BugsnagPerformance.getSpanControls(). The NativeSpanQuery class allows you to specify the name of the span you want to retrieve and, if found, returns a NativeSpanControl object: allowing the span to be used in parent hierarchies and for supported operations to be executed on the native span from JavaScript code:

import BugsnagPerformance from '@bugsnag/react-native-performance'
import { NativeSpanQuery } from '@bugsnag/plugin-react-native-span-access'

// Query the SDK for a native span by name
const nativeSpan: NativeSpanControl | null = 
  BugsnagPerformance.getSpanControls(new NativeSpanQuery('login'))

if (nativeSpan) {
  // NativeSpanControl can be used...
  // ... as a parent context for JS spans directly
  BugsnagPerformance.startSpan('js-login-view', { parentContext: nativeSpanControl })

  // ... or to perform operations on the native span.
  // The NativeSpanMutator (spanMutator) is only valid for the duration of the lambda call. 
  // Returns true only if the changes were applied, or false otherwise.
  const spanWasUpdated = await nativeSpanControl.updateSpan(spanMutator => {
    spanMutator.setAttribute('my.attribute', 'from JS')
    spanMutator.end()
  })
}

If the span does not exist, has already ended or is no longer valid, getSpanControls will return null. If multiple spans with the same name are open, only the most recent one will be returned.

To avoid memory leaks caused by spans not being ended, spans older than 10 minutes are removed from tracked memory to allow them to be deallocated.