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.
For access to spans created in JavaScript from elsewhere in your JavaScript code:
Install the @bugsnag/plugin-named-spans
package:
yarn add @bugsnag/plugin-named-spans
# or
npm install --save @bugsnag/plugin-named-spans
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()]
})
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.
For access to spans created in native Android and iOS code from your JavaScript code:
Install the @bugsnag/plugin-react-native-span-access
package:
yarn add @bugsnag/plugin-react-native-span-access
# or
npm install --save @bugsnag/plugin-react-native-span-access
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"))
}
run pod install
in your iOS project directory to ensure the plugin is linked correctly:
npx pod-install
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:
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())
})
BugsnagPerformanceConfiguration *config = [BugsnagPerformanceConfiguration loadConfig];
[config addPlugin:[BugsnagNativeSpansPlugin new]];
[BugsnagPerformance startWithConfiguration:config];
let config = BugsnagPerformanceConfiguration.loadConfig()
config.add(BugsnagNativeSpansPlugin())
BugsnagPerformance.start(configuration: config)
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()]
})
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.