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.

Maintaining span context

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.

Automatic context creation

By default, when a span is created it becomes the parent span for other spans that start on the same thread. 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.

BugsnagPerformanceSpan *span1 = [BugsnagPerformance startSpanWithName:@"span1"];
BugsnagPerformanceSpan *span2 = [BugsnagPerformance startSpanWithName:@"span2"];
[span2 end];
[span1 end];
BugsnagPerformanceSpan *span3 = [BugsnagPerformance startSpanWithName:@"span3"];
[span3 end];
let span1 = BugsnagPerformance.startSpan(name: "span1")
let span2 = BugsnagPerformance.startSpan(name: "span2")
span2.end()
span1.end()
let span3 = BugsnagPerformance.startSpan(name: "span3")
span3.end()

BugSnag uses Apple’s Activity Tracing API to maintain the hierarchy of open spans across threads automatically.

Like us, some other monitoring vendor SDKs make use of the Activity Tracing API. This API does not play well with multiple consumers. Attempting to use BugSnag Performance alongside one of these other SDKs may have unwanted impact on the data collected.

Preventing new contexts

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:

BugsnagPerformanceSpanOptions *options = [BugsnagPerformanceSpanOptions new];
options.makeCurrentContext = NO;
[BugsnagPerformance startSpanWithName:@"childless" options:options];
BugsnagPerformance.startSpan(
    name: "childless",
    options: BugsnagPerformanceSpanOptions.setMakeCurrentContext(false))

For example, in the following snippet span1 becomes the parent of both span2 and span3:

BugsnagPerformanceSpan *span1 = [BugsnagPerformance startSpanWithName:@"span1"];
BugsnagPerformanceSpanOptions *options = [BugsnagPerformanceSpanOptions new];
options.makeCurrentContext = NO;
BugsnagPerformanceSpan *span2 = [BugsnagPerformance startSpanWithName:@"span2" 
                                                              options:options];
BugsnagPerformanceSpan *span3 = [BugsnagPerformance startSpanWithName:@"span3"];
[span3 end];
[span2 end];
[span1 end];
let span1 = BugsnagPerformance.startSpan(name: "span1")
let span2 = BugsnagPerformance.startSpan(
    name: "span2",
    options: BugsnagPerformanceSpanOptions.setMakeCurrentContext(false))
let span3 = BugsnagPerformance.startSpan(name: "span3")
span3.end()
span2.end()
span1.end()

Setting contexts manually

You can set a parent of a span manually using the parentContext span option:

BugsnagPerformanceSpanOptions *options = [BugsnagPerformanceSpanOptions new];
options.parentContext = manualParentSpan;
[BugsnagPerformance startSpanWithName:@"child-span" options:options];
BugsnagPerformance.startSpan(
    name: "child-span", 
    options: BugsnagPerformanceSpanOptions.setParentContext(manualParentSpan))

If a span is known to be independent of any other open spans, you can also set the parentContext span option to nil, which will prevent it becoming a child:

BugsnagPerformanceSpanOptions *options = [BugsnagPerformanceSpanOptions new];
options.parentContext = nil;
[BugsnagPerformance startSpanWithName:@"top-level" options:options];
BugsnagPerformance.startSpan(
    name: "top-level", 
    options: BugsnagPerformanceSpanOptions.setParentContext(nil))

Setting the context from remote sources

If you want operations on another process or non-native layer (such as JavaScript spans in React Native) to be children or parents of your spans, you can encode any span context into a string which can be parsed back into a parent span context by another layer of your app:

BugsnagPerformanceSpan *span = [BugsnagPerformance startSpanWithName:@"remote-parent"];
NSString *encodedSpanContext = [span encodedAsTraceParent]
let span = BugsnagPerformance.startSpan(name: "remote-parent")
let encodedSpanContext = span.encodedAsTraceParent()

This works with any span context, so if you don’t have a BugsnagPerformanceSpan and need to encode the “current” context for the thread:

BugsnagPerformanceSpanContext *currentSpanContext = [BugsnagPerformance currentContext];
NSString *encodedSpanContext = [currentSpanContext encodedAsTraceParent]
let currentSpanContext = BugsnagPerformance.currentContext()
let encodedSpanContext = currentSpanContext.encodedAsTraceParent()

The encodedSpanContext is a string formatted according to the traceparent header specification (version 00) and can be passed between any layers of your app (or system) and used as a parent when creating a new span:

NSString *encodedSpanContext; // encoded traceparent header from external source
BugsnagPerformanceRemoteSpanContext *remoteParent =
    [BugsnagPerformanceRemoteSpanContext contextWithTraceParentString:encodedSpanContext]

// Create span with remote context
BugsnagPerformanceSpanOptions *options = [BugsnagPerformanceSpanOptions new];
options.parentContext = remoteParent;
[BugsnagPerformance startSpanWithName:@"child-of-remote" options:options];
let encodedSpanContext: String // encoded traceparent header from external source
let remoteParent = 
    BugsnagPerformanceRemoteSpanContext.contextWithTraceParentString(encodedSpanContext)

// Create span with remote context
BugsnagPerformance.startSpan(
    name: "child-of-remote", 
    options: BugsnagPerformanceSpanOptions.setParentContext(remoteParent))

The equivalent functionality for encoding and parsing span contexts can be found in the Android and React Native guides.