diff --git a/.size-limit.js b/.size-limit.js index b28892aecb89..e97e15f6cd4e 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -187,7 +187,7 @@ module.exports = [ path: createCDNPath('bundle.tracing.min.js'), gzip: false, brotli: false, - limit: '113 KB', + limit: '120 KB', }, { name: 'CDN Bundle (incl. Tracing, Replay) - uncompressed', diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 840992c4ea79..2387523d46ee 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -52,6 +52,7 @@ import { dropUndefinedKeys } from './utils-hoist/object'; import { SyncPromise, rejectedSyncPromise, resolvedSyncPromise } from './utils-hoist/syncpromise'; import { parseSampleRate } from './utils/parseSampleRate'; import { prepareEvent } from './utils/prepareEvent'; +import { showSpanDropWarning } from './utils/spanUtils'; const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; @@ -977,6 +978,7 @@ function processBeforeSend( if (processedSpan) { processedSpans.push(processedSpan); } else { + showSpanDropWarning(); client.recordDroppedEvent('before_send', 'span'); } } diff --git a/packages/core/src/envelope.ts b/packages/core/src/envelope.ts index ddeb2ce21997..8ecdeb0d604f 100644 --- a/packages/core/src/envelope.ts +++ b/packages/core/src/envelope.ts @@ -24,7 +24,7 @@ import { createSpanEnvelopeItem, getSdkMetadataForEnvelopeHeader, } from './utils-hoist/envelope'; -import { spanToJSON } from './utils/spanUtils'; +import { showSpanDropWarning, spanToJSON } from './utils/spanUtils'; /** * Apply SdkInfo (name, version, packages, integrations) to the corresponding event key. @@ -122,7 +122,13 @@ export function createSpanEnvelope(spans: [SentrySpan, ...SentrySpan[]], client? const beforeSendSpan = client && client.getOptions().beforeSendSpan; const convertToSpanJSON = beforeSendSpan - ? (span: SentrySpan) => beforeSendSpan(spanToJSON(span) as SpanJSON) + ? (span: SentrySpan) => { + const spanJson = beforeSendSpan(spanToJSON(span) as SpanJSON); + if (!spanJson) { + showSpanDropWarning(); + } + return spanJson; + } : (span: SentrySpan) => spanToJSON(span); const items: SpanItem[] = []; diff --git a/packages/core/src/utils/spanUtils.ts b/packages/core/src/utils/spanUtils.ts index 5f0c443919a3..d9232b1f48bc 100644 --- a/packages/core/src/utils/spanUtils.ts +++ b/packages/core/src/utils/spanUtils.ts @@ -17,6 +17,7 @@ import type { MetricType } from '../metrics/types'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes'; import type { SentrySpan } from '../tracing/sentrySpan'; import { SPAN_STATUS_OK, SPAN_STATUS_UNSET } from '../tracing/spanstatus'; +import { consoleSandbox } from '../utils-hoist/logger'; import { addNonEnumerableProperty, dropUndefinedKeys } from '../utils-hoist/object'; import { timestampInSeconds } from '../utils-hoist/time'; import { generateSentryTraceHeader } from '../utils-hoist/tracing'; @@ -26,6 +27,9 @@ import { _getSpanForScope } from './spanOnScope'; export const TRACE_FLAG_NONE = 0x0; export const TRACE_FLAG_SAMPLED = 0x1; +// todo(v9): Remove this once we've stopped dropping spans via `beforeSendSpan` +let hasShownSpanDropWarning = false; + /** * Convert a span to a trace context, which can be sent as the `trace` context in an event. * By default, this will only include trace_id, span_id & parent_span_id. @@ -280,3 +284,20 @@ export function updateMetricSummaryOnActiveSpan( updateMetricSummaryOnSpan(span, metricType, sanitizedName, value, unit, tags, bucketKey); } } + +/** + * Logs a warning once if `beforeSendSpan` is used to drop spans. + * + * todo(v9): Remove this once we've stopped dropping spans via `beforeSendSpan`. + */ +export function showSpanDropWarning(): void { + if (!hasShownSpanDropWarning) { + consoleSandbox(() => { + // eslint-disable-next-line no-console + console.warn( + '[Sentry] Deprecation warning: Returning null from `beforeSendSpan` will be disallowed from SDK version 9.0.0 onwards. The callback will only support mutating spans. To drop certain spans, configure the respective integrations directly.', + ); + }); + hasShownSpanDropWarning = true; + } +}