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))