diff --git a/packages/core/src/utils/spanUtils.ts b/packages/core/src/utils/spanUtils.ts index 094f6674121c..8478778d7dd5 100644 --- a/packages/core/src/utils/spanUtils.ts +++ b/packages/core/src/utils/spanUtils.ts @@ -85,12 +85,10 @@ function ensureTimestampInSeconds(timestamp: number): number { /** * Convert a span to a JSON representation. - * Note that all fields returned here are optional and need to be guarded against. - * - * Note: Because of this, we currently have a circular type dependency (which we opted out of in package.json). - * This is not avoidable as we need `spanToJSON` in `spanUtils.ts`, which in turn is needed by `span.ts` for backwards compatibility. - * And `spanToJSON` needs the Span class from `span.ts` to check here. */ +// Note: Because of this, we currently have a circular type dependency (which we opted out of in package.json). +// This is not avoidable as we need `spanToJSON` in `spanUtils.ts`, which in turn is needed by `span.ts` for backwards compatibility. +// And `spanToJSON` needs the Span class from `span.ts` to check here. export function spanToJSON(span: Span): Partial { if (spanIsSentrySpan(span)) { return span.getSpanJSON(); diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index 58f6ba53303e..75c0c8be5ed9 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -178,7 +178,7 @@ function createTransactionForOtelSpan(span: ReadableSpan): TransactionEvent { data: attributes, origin, op, - status: getStatusMessage(status), + status: getStatusMessage(status), // As per protocol, span status is allowed to be undefined }); const transactionEvent: TransactionEvent = { @@ -252,7 +252,7 @@ function createAndFinishSpanForOtelSpan(node: SpanNode, spans: SpanJSON[], remai start_timestamp: convertOtelTimeToSeconds(startTime), // This is [0,0] by default in OTEL, in which case we want to interpret this as no end time timestamp: convertOtelTimeToSeconds(endTime) || undefined, - status: getStatusMessage(status), + status: getStatusMessage(status), // As per protocol, span status is allowed to be undefined op, origin, _metrics_summary: getMetricSummaryJsonForSpan(span as unknown as Span), diff --git a/packages/opentelemetry/src/trace.ts b/packages/opentelemetry/src/trace.ts index 945e60a811f1..d47c8db5ec2b 100644 --- a/packages/opentelemetry/src/trace.ts +++ b/packages/opentelemetry/src/trace.ts @@ -12,6 +12,7 @@ import { getDynamicSamplingContextFromClient, getRootSpan, handleCallbackErrors, + spanToJSON, } from '@sentry/core'; import type { Client, Scope } from '@sentry/types'; import { continueTraceAsRemoteSpan, getSamplingDecision, makeTraceState } from './propagator'; @@ -46,7 +47,10 @@ export function startSpan(options: OpenTelemetrySpanContext, callback: (span: return handleCallbackErrors( () => callback(span), () => { - span.setStatus({ code: SpanStatusCode.ERROR }); + // Only set the span status to ERROR when there wasn't any status set before, in order to avoid stomping useful span statuses + if (spanToJSON(span).status === undefined) { + span.setStatus({ code: SpanStatusCode.ERROR }); + } }, () => span.end(), ); @@ -82,7 +86,10 @@ export function startSpanManual( return handleCallbackErrors( () => callback(span, () => span.end()), () => { - span.setStatus({ code: SpanStatusCode.ERROR }); + // Only set the span status to ERROR when there wasn't any status set before, in order to avoid stomping useful span statuses + if (spanToJSON(span).status === undefined) { + span.setStatus({ code: SpanStatusCode.ERROR }); + } }, ); });