Skip to content

Commit 284e90d

Browse files
author
Luca Forstner
authored
fix(opentelemetry): Do not stomp span status when startSpan callback throws (#11170)
1 parent 32b6a99 commit 284e90d

File tree

3 files changed

+14
-9
lines changed

3 files changed

+14
-9
lines changed

packages/core/src/utils/spanUtils.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,10 @@ function ensureTimestampInSeconds(timestamp: number): number {
8585

8686
/**
8787
* Convert a span to a JSON representation.
88-
* Note that all fields returned here are optional and need to be guarded against.
89-
*
90-
* Note: Because of this, we currently have a circular type dependency (which we opted out of in package.json).
91-
* This is not avoidable as we need `spanToJSON` in `spanUtils.ts`, which in turn is needed by `span.ts` for backwards compatibility.
92-
* And `spanToJSON` needs the Span class from `span.ts` to check here.
9388
*/
89+
// Note: Because of this, we currently have a circular type dependency (which we opted out of in package.json).
90+
// This is not avoidable as we need `spanToJSON` in `spanUtils.ts`, which in turn is needed by `span.ts` for backwards compatibility.
91+
// And `spanToJSON` needs the Span class from `span.ts` to check here.
9492
export function spanToJSON(span: Span): Partial<SpanJSON> {
9593
if (spanIsSentrySpan(span)) {
9694
return span.getSpanJSON();

packages/opentelemetry/src/spanExporter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ function createTransactionForOtelSpan(span: ReadableSpan): TransactionEvent {
178178
data: attributes,
179179
origin,
180180
op,
181-
status: getStatusMessage(status),
181+
status: getStatusMessage(status), // As per protocol, span status is allowed to be undefined
182182
});
183183

184184
const transactionEvent: TransactionEvent = {
@@ -252,7 +252,7 @@ function createAndFinishSpanForOtelSpan(node: SpanNode, spans: SpanJSON[], remai
252252
start_timestamp: convertOtelTimeToSeconds(startTime),
253253
// This is [0,0] by default in OTEL, in which case we want to interpret this as no end time
254254
timestamp: convertOtelTimeToSeconds(endTime) || undefined,
255-
status: getStatusMessage(status),
255+
status: getStatusMessage(status), // As per protocol, span status is allowed to be undefined
256256
op,
257257
origin,
258258
_metrics_summary: getMetricSummaryJsonForSpan(span as unknown as Span),

packages/opentelemetry/src/trace.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
getDynamicSamplingContextFromClient,
1313
getRootSpan,
1414
handleCallbackErrors,
15+
spanToJSON,
1516
} from '@sentry/core';
1617
import type { Client, Scope } from '@sentry/types';
1718
import { continueTraceAsRemoteSpan, getSamplingDecision, makeTraceState } from './propagator';
@@ -46,7 +47,10 @@ export function startSpan<T>(options: OpenTelemetrySpanContext, callback: (span:
4647
return handleCallbackErrors(
4748
() => callback(span),
4849
() => {
49-
span.setStatus({ code: SpanStatusCode.ERROR });
50+
// Only set the span status to ERROR when there wasn't any status set before, in order to avoid stomping useful span statuses
51+
if (spanToJSON(span).status === undefined) {
52+
span.setStatus({ code: SpanStatusCode.ERROR });
53+
}
5054
},
5155
() => span.end(),
5256
);
@@ -82,7 +86,10 @@ export function startSpanManual<T>(
8286
return handleCallbackErrors(
8387
() => callback(span, () => span.end()),
8488
() => {
85-
span.setStatus({ code: SpanStatusCode.ERROR });
89+
// Only set the span status to ERROR when there wasn't any status set before, in order to avoid stomping useful span statuses
90+
if (spanToJSON(span).status === undefined) {
91+
span.setStatus({ code: SpanStatusCode.ERROR });
92+
}
8693
},
8794
);
8895
});

0 commit comments

Comments
 (0)