From 8300aeb2a65b498498d083d61e1ff7d492374e16 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Sat, 21 Dec 2024 18:49:23 +0000 Subject: [PATCH] fix: Correctly resolve debug IDs for ANR events with custom appRoot --- .../suites/anr/app-path.mjs | 36 +++++++++++++++++++ .../node-integration-tests/suites/anr/test.ts | 28 ++++++++++++--- packages/node/src/integrations/anr/worker.ts | 15 +++++--- 3 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 dev-packages/node-integration-tests/suites/anr/app-path.mjs diff --git a/dev-packages/node-integration-tests/suites/anr/app-path.mjs b/dev-packages/node-integration-tests/suites/anr/app-path.mjs new file mode 100644 index 000000000000..b7d32e1aa9b2 --- /dev/null +++ b/dev-packages/node-integration-tests/suites/anr/app-path.mjs @@ -0,0 +1,36 @@ +import * as assert from 'assert'; +import * as crypto from 'crypto'; +import * as path from 'path'; +import * as url from 'url'; + +import * as Sentry from '@sentry/node'; + +global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; + +const __dirname = path.dirname(url.fileURLToPath(import.meta.url)); + +setTimeout(() => { + process.exit(); +}, 10000); + +Sentry.init({ + dsn: process.env.SENTRY_DSN, + release: '1.0', + autoSessionTracking: false, + integrations: [Sentry.anrIntegration({ captureStackTrace: true, anrThreshold: 100, appRootPath: __dirname })], +}); + +Sentry.setUser({ email: 'person@home.com' }); +Sentry.addBreadcrumb({ message: 'important message!' }); + +function longWork() { + for (let i = 0; i < 20; i++) { + const salt = crypto.randomBytes(128).toString('base64'); + const hash = crypto.pbkdf2Sync('myPassword', salt, 10000, 512, 'sha512'); + assert.ok(hash); + } +} + +setTimeout(() => { + longWork(); +}, 1000); diff --git a/dev-packages/node-integration-tests/suites/anr/test.ts b/dev-packages/node-integration-tests/suites/anr/test.ts index d1d9c684bf60..cd7df2a86314 100644 --- a/dev-packages/node-integration-tests/suites/anr/test.ts +++ b/dev-packages/node-integration-tests/suites/anr/test.ts @@ -31,20 +31,20 @@ const ANR_EVENT = { mechanism: { type: 'ANR' }, stacktrace: { frames: expect.arrayContaining([ - { + expect.objectContaining({ colno: expect.any(Number), lineno: expect.any(Number), filename: expect.any(String), function: '?', in_app: true, - }, - { + }), + expect.objectContaining({ colno: expect.any(Number), lineno: expect.any(Number), filename: expect.any(String), function: 'longWork', in_app: true, - }, + }), ]), }, }, @@ -123,6 +123,26 @@ conditionalTest({ min: 16 })('should report ANR when event loop blocked', () => .start(done); }); + test('Custom appRootPath', done => { + const ANR_EVENT_WITH_SPECIFIC_DEBUG_META: Event = { + ...ANR_EVENT_WITH_SCOPE, + debug_meta: { + images: [ + { + type: 'sourcemap', + debug_id: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa', + code_file: 'app:///app-path.mjs', + }, + ], + }, + }; + + createRunner(__dirname, 'app-path.mjs') + .withMockSentryServer() + .expect({ event: ANR_EVENT_WITH_SPECIFIC_DEBUG_META }) + .start(done); + }); + test('multiple events via maxAnrEvents', done => { createRunner(__dirname, 'basic-multiple.mjs') .withMockSentryServer() diff --git a/packages/node/src/integrations/anr/worker.ts b/packages/node/src/integrations/anr/worker.ts index f412806b1117..117cccfe8904 100644 --- a/packages/node/src/integrations/anr/worker.ts +++ b/packages/node/src/integrations/anr/worker.ts @@ -91,22 +91,27 @@ function applyDebugMeta(event: Event): void { return; } + const normalisedDebugImages = options.appRootPath ? {} : mainDebugImages; + if (options.appRootPath) { + for (const [path, debugId] of Object.entries(mainDebugImages)) { + normalisedDebugImages[normalizeUrlToBase(path, options.appRootPath)] = debugId; + } + } + const filenameToDebugId = new Map(); for (const exception of event.exception?.values || []) { for (const frame of exception.stacktrace?.frames || []) { const filename = frame.abs_path || frame.filename; - if (filename && mainDebugImages[filename]) { - filenameToDebugId.set(filename, mainDebugImages[filename] as string); + if (filename && normalisedDebugImages[filename]) { + filenameToDebugId.set(filename, normalisedDebugImages[filename] as string); } } } if (filenameToDebugId.size > 0) { const images: DebugImage[] = []; - for (const [filename, debug_id] of filenameToDebugId.entries()) { - const code_file = options.appRootPath ? normalizeUrlToBase(filename, options.appRootPath) : filename; - + for (const [code_file, debug_id] of filenameToDebugId.entries()) { images.push({ type: 'sourcemap', code_file,