Skip to content

Commit 1052e88

Browse files
committed
feat: start a root span with spanOptions.parent = null
1 parent 584eeab commit 1052e88

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

packages/opentelemetry-api/src/trace/SpanOptions.ts

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ export interface SpanOptions {
4444
* A parent `SpanContext` (or `Span`, for convenience) that the newly-started
4545
* span will be the child of. This overrides the parent span extracted from
4646
* the currently active context.
47+
*
48+
* A null value here should prevent the SDK from extracting a parent from
49+
* the current context, forcing the new span to be a root span.
4750
*/
4851
parent?: Span | SpanContext | null;
4952

packages/opentelemetry-tracing/src/Tracer.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ export class Tracer implements api.Tracer {
6666
options: api.SpanOptions = {},
6767
context = api.context.active()
6868
): api.Span {
69-
const parentContext = options.parent
70-
? getContext(options.parent)
71-
: getParentSpanContext(context);
69+
const parentContext = getParent(options, context);
7270
// make sampling decision
7371
const samplingDecision = this._sampler.shouldSample(parentContext);
7472
const spanId = randomSpanId();
@@ -149,6 +147,19 @@ export class Tracer implements api.Tracer {
149147
}
150148
}
151149

150+
/**
151+
* Get the parent to assign to a started span. If options.parent is null,
152+
* do not assign a parent.
153+
*
154+
* @param options span options
155+
* @param context context to check for parent
156+
*/
157+
function getParent(options: api.SpanOptions, context: api.Context) {
158+
if (options.parent === null) return undefined;
159+
if (options.parent) return getContext(options.parent);
160+
return getParentSpanContext(context);
161+
}
162+
152163
function getContext(span: api.Span | api.SpanContext) {
153164
return isSpan(span) ? span.context() : span;
154165
}

packages/opentelemetry-tracing/test/BasicTracerProvider.test.ts

+15
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,21 @@ describe('BasicTracerProvider', () => {
239239
childSpan.end();
240240
});
241241

242+
it('should create a root span when parent is null', () => {
243+
const tracer = new BasicTracerProvider().getTracer('default');
244+
const span = tracer.startSpan('my-span');
245+
const overrideParent = tracer.startSpan('my-parent-override-span');
246+
const rootSpan = tracer.startSpan(
247+
'root-span',
248+
{ parent: null },
249+
setActiveSpan(Context.ROOT_CONTEXT, span)
250+
);
251+
const context = rootSpan.context();
252+
assert.notStrictEqual(context.traceId, overrideParent.context().traceId);
253+
span.end();
254+
rootSpan.end();
255+
})
256+
242257
it('should start a span with name and with invalid parent span', () => {
243258
const tracer = new BasicTracerProvider().getTracer('default');
244259
const span = tracer.startSpan(

0 commit comments

Comments
 (0)