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, where the children are spans started from within the context of their parent. This page describes the tools available in the SDK to control these parent-child relationships.
By default, when a span is created it becomes the parent span for other spans that start after it. We call this parent span the “current span context” and it remains until it is ended or another span becomes the current context.
For example, in the following snippet span1
becomes the current span context and span2
automatically becomes a child of span1
. span3
then becomes the new current context, but with no parent span because span1
and span2
have already ended.
const span1 = BugsnagPerformance.startSpan("span1")
const span2 = BugsnagPerformance.startSpan("span2")
span2.end()
span1.end()
const span3 = BugsnagPerformance.startSpan("span3")
span3.end()
To prevent a span becoming the new current context when it is created, and so being the parent of future spans, set the makeCurrentContext
span option:
BugsnagPerformance.startSpan("childless", { makeCurrentContext: false })
For example, in the following snippet span1
becomes the parent of both span2
and span3
:
const span1 = BugsnagPerformance.startSpan("span1")
const span2 = BugsnagPerformance.startSpan("span2", { makeCurrentContext: false })
const span3 = BugsnagPerformance.startSpan("span3")
span3.end()
span2.end()
span1.end()
You can set a parent of a span manually using the parentContext
span option:
BugsnagPerformance.startSpan("child-span", { parentContext: manualParentSpan })
If a span is known to be independent of any other open spans, you can also set the parentContext
span option to null
, which will prevent it from becoming a child:
BugsnagPerformance.startSpan("top-level", { parentContext: null })
You can use the @bugsnag/plugin-named-spans
to track open spans and access them by name from different parts of your codebase. See Named span access for details.
The current span context is stored globally, therefore when starting spans in async methods and promises it is important to set the makeCurrentContext
span option to false
to prevent spans from automatically becoming the current context outside of the async operation.
We also recommend using the parentContext
span option to ensure that async spans become children of the parent operation, as it may not be the current context by the time the task is executed.
For example in the following snippet, without the additional options the spans in each task would become children of each other based on order of execution:
const parentSpan = BugsnagPerformance.startSpan('parent-span')
const task = async (value) => {
const taskSpan = BugsnagPerformance.startSpan('task-span', {
makeCurrentContext: false,
parentContext: parentSpan
})
// do some work
taskSpan.end()
}
const tasks = collection.map(value => task(value))
Promise.all(tasks).finally(() => {
// close the parent span when all tasks are complete
parentSpan.end()
})
The SDK provides two mechanisms to allow you include remote (e.g. non-JavaScript) spans in the span hierarchy:
Use the Named span access plugin to track open spans in your native layer, or elsewhere in your JavaScript code. This provides remote access to a native span object that can be used as the parent of local JavaScript spans.
Alternatively, if you have an existing communication mechanism between your JavaScript and native layers, you can simple encode the span context as a string and send it to another layer to be used as a parent context.
The SDK provides the following utility functions to encode and decode spans, using the traceparent header format (version 00
):
const span = BugsnagPerformance.startSpan("remote-parent")
const encodedSpanContext = RemoteParentContext.toTraceParentString(span)
This works with any span context, so if you don’t have a Span
and need to encode the “current” context for the thread:
const currentSpanContext = BugsnagPerformance.currentSpanContext
const encodedSpanContext = RemoteParentContext.toTraceParentString(currentSpanContext)
The encodedSpanContext
can then be used as a parent when creating a new span:
const encodedSpanContext // encoded traceparent header from external source
const remoteParent = RemoteParentContext.parseTraceParent(encodedSpanContext)
const span = BugsnagPerformance.startSpan("child-of-remote", { parentContext: remoteParent })