diff --git a/.changeset/sentry-trace-lifecycle-static.md b/.changeset/sentry-trace-lifecycle-static.md new file mode 100644 index 0000000..36159d4 --- /dev/null +++ b/.changeset/sentry-trace-lifecycle-static.md @@ -0,0 +1,5 @@ +--- +'uptide': patch +--- + +The Sentry 10 to 11 pack no longer reports `beforeSendTransaction` or `ignoreTransactions` in a `Sentry.init` that sets `traceLifecycle`: the option keeps transactions, so they still work. diff --git a/packages/core/src/packs/sentry/detect.ts b/packages/core/src/packs/sentry/detect.ts index 20066b2..e5abe22 100644 --- a/packages/core/src/packs/sentry/detect.ts +++ b/packages/core/src/packs/sentry/detect.ts @@ -29,10 +29,19 @@ import { const SOURCE = /\.[cm]?[jt]sx?$/; const NEXT_CONFIG = /(?:^|\/)next\.config\.(?:js|mjs|cjs|ts|mts)$/; -/** `Sentry.init` option paths found in a file, as sites. */ -export function initOptionSites(paths: readonly string[]) { +/** + * `Sentry.init` option paths found in a file, as sites. `unless` names options of the same + * object that keep the path working (`traceLifecycle` keeps `beforeSendTransaction`): an object + * that sets one is not reported. + */ +export function initOptionSites(paths: readonly string[], unless: readonly string[] = []) { return (text: string, file: string): SourceSite[] => - SOURCE.test(file) ? propertySites(initOptions(parse(text, file)), paths) : []; + SOURCE.test(file) + ? propertySites( + initOptions(parse(text, file)).filter((o) => !unless.some((key) => propertyAt(o, key))), + paths, + ) + : []; } /** Option paths of the named integrations' options objects. */ diff --git a/packages/core/src/packs/sentry/rules.ts b/packages/core/src/packs/sentry/rules.ts index a027bec..a3a15e0 100644 --- a/packages/core/src/packs/sentry/rules.ts +++ b/packages/core/src/packs/sentry/rules.ts @@ -205,7 +205,7 @@ export const SENTRY_RULES: readonly SentryRule[] = [ kinds: [...INIT_KINDS], symbols: symbols(['ignoreTransactions']), message: named(['ignoreTransactions']), - detect: initOptionSites(['ignoreTransactions']), + detect: initOptionSites(['ignoreTransactions'], ['traceLifecycle']), guide: `ignoreTransactions still compiles (deprecated) but does nothing with span streaming (${anchor('replacing-ignoretransactions-with-ignorespans')}). Options: (a) ignoreSpans with the same patterns — it matches every span, not only the root, so prefer the object form { name, attributes: { 'sentry.op': ... } } where a child span could share the name; (b) traceLifecycle: 'static' to keep transactions (temporary: planned for removal). Span names are low-cardinality in v11 and ignoreSpans runs at span start: a pattern matching a raw URL or SQL text may need to match url.path or db.query.text instead. ${CHOOSE}`, }, { @@ -216,7 +216,7 @@ export const SENTRY_RULES: readonly SentryRule[] = [ kinds: [...INIT_KINDS], symbols: symbols(['beforeSendTransaction']), message: named(['beforeSendTransaction']), - detect: initOptionSites(['beforeSendTransaction']), + detect: initOptionSites(['beforeSendTransaction'], ['traceLifecycle']), guide: `beforeSendTransaction still compiles (deprecated) but no transaction events exist with span streaming (${anchor('replacing-beforesendtransaction')}). Options: (a) move scrubbing to beforeSendSpan guarded by span.is_segment, and dropping to ignoreSpans (beforeSendSpan cannot drop); (b) traceLifecycle: 'static' to keep transactions. Scope tags and extra no longer reach spans: use setAttribute(s). ${CHOOSE}`, }, { diff --git a/packages/core/src/packs/sentry/sentry.test.ts b/packages/core/src/packs/sentry/sentry.test.ts index 1edb8ba..5ed8686 100644 --- a/packages/core/src/packs/sentry/sentry.test.ts +++ b/packages/core/src/packs/sentry/sentry.test.ts @@ -147,6 +147,20 @@ describe('compiler-blind detection', () => { ]); }); + it("keeps beforeSendTransaction and ignoreTransactions where traceLifecycle: 'static' is set", () => { + const init = (extra: string) => + [ + "import * as Sentry from '@sentry/browser';", + `Sentry.init({ ${extra}beforeSendTransaction: (e) => e, ignoreTransactions: ['x'] });`, + '', + ].join('\n'); + expect(sites(sentryBrowserPack, 'sentry.ts', init(''))).toEqual([ + 'ignore-transactions:2', + 'before-send-transaction:2', + ]); + expect(sites(sentryBrowserPack, 'sentry.ts', init("traceLifecycle: 'static', "))).toEqual([]); + }); + it('ignores the same reads on objects that are not Sentry spans', () => { const text = [ "import * as Sentry from '@sentry/browser';",