diff --git a/dev-packages/node-core-integration-tests/suites/anr/app-path.mjs b/dev-packages/node-core-integration-tests/suites/anr/app-path.mjs index 28f245851b01..1c5f141021a8 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/app-path.mjs +++ b/dev-packages/node-core-integration-tests/suites/anr/app-path.mjs @@ -4,6 +4,7 @@ import * as crypto from 'crypto'; import * as path from 'path'; import * as url from 'url'; import { setupOtel } from '../../utils/setupOtel.js'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -32,6 +33,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-core-integration-tests/suites/anr/basic-multiple.mjs b/dev-packages/node-core-integration-tests/suites/anr/basic-multiple.mjs index 1caf96d3abdb..6b0e1de340dd 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/basic-multiple.mjs +++ b/dev-packages/node-core-integration-tests/suites/anr/basic-multiple.mjs @@ -2,6 +2,7 @@ import * as Sentry from '@sentry/node-core'; import * as assert from 'assert'; import * as crypto from 'crypto'; import { setupOtel } from '../../utils/setupOtel.js'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -28,10 +29,11 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); -setTimeout(() => { - longWork(); -}, 4000); + // Second blocking event for maxAnrEvents test + setTimeout(() => { + longWork(); + }, 2000); +}); diff --git a/dev-packages/node-core-integration-tests/suites/anr/basic-session.js b/dev-packages/node-core-integration-tests/suites/anr/basic-session.js index e89a65e79ad2..229f4eb28d5b 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/basic-session.js +++ b/dev-packages/node-core-integration-tests/suites/anr/basic-session.js @@ -3,6 +3,7 @@ const assert = require('assert'); const Sentry = require('@sentry/node-core'); const { setupOtel } = require('../../utils/setupOtel.js'); +const { waitForDebuggerReady } = require('@sentry-internal/test-utils'); setTimeout(() => { process.exit(); @@ -27,6 +28,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-core-integration-tests/suites/anr/basic.js b/dev-packages/node-core-integration-tests/suites/anr/basic.js index 9010fb296c48..d02ed4f254f1 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/basic.js +++ b/dev-packages/node-core-integration-tests/suites/anr/basic.js @@ -3,6 +3,7 @@ const assert = require('assert'); const Sentry = require('@sentry/node-core'); const { setupOtel } = require('../../utils/setupOtel.js'); +const { waitForDebuggerReady } = require('@sentry-internal/test-utils'); global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -29,6 +30,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-core-integration-tests/suites/anr/basic.mjs b/dev-packages/node-core-integration-tests/suites/anr/basic.mjs index 109a201ecb98..71525c7e9ebe 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/basic.mjs +++ b/dev-packages/node-core-integration-tests/suites/anr/basic.mjs @@ -2,6 +2,7 @@ import * as Sentry from '@sentry/node-core'; import * as assert from 'assert'; import * as crypto from 'crypto'; import { setupOtel } from '../../utils/setupOtel.js'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -28,11 +29,11 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); -// Ensure we only send one event even with multiple blocking events -setTimeout(() => { - longWork(); -}, 4000); + // Ensure we only send one event even with multiple blocking events + setTimeout(() => { + longWork(); + }, 2000); +}); diff --git a/dev-packages/node-core-integration-tests/suites/anr/forked.js b/dev-packages/node-core-integration-tests/suites/anr/forked.js index 2fd7a0678e8d..5dd6c93e82ef 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/forked.js +++ b/dev-packages/node-core-integration-tests/suites/anr/forked.js @@ -3,6 +3,7 @@ const assert = require('assert'); const Sentry = require('@sentry/node-core'); const { setupOtel } = require('../../utils/setupOtel.js'); +const { waitForDebuggerReady } = require('@sentry-internal/test-utils'); setTimeout(() => { process.exit(); @@ -28,6 +29,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-core-integration-tests/suites/anr/indefinite.mjs b/dev-packages/node-core-integration-tests/suites/anr/indefinite.mjs index db9217ec34b2..0b8d33757e90 100644 --- a/dev-packages/node-core-integration-tests/suites/anr/indefinite.mjs +++ b/dev-packages/node-core-integration-tests/suites/anr/indefinite.mjs @@ -2,6 +2,7 @@ import * as Sentry from '@sentry/node-core'; import * as assert from 'assert'; import * as crypto from 'crypto'; import { setupOtel } from '../../utils/setupOtel.js'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; setTimeout(() => { process.exit(); @@ -27,6 +28,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/app-path.mjs b/dev-packages/node-integration-tests/suites/anr/app-path.mjs index 5ace9ebbb3e8..e0a13f7e6869 100644 --- a/dev-packages/node-integration-tests/suites/anr/app-path.mjs +++ b/dev-packages/node-integration-tests/suites/anr/app-path.mjs @@ -3,6 +3,7 @@ import * as assert from 'assert'; import * as crypto from 'crypto'; import * as path from 'path'; import * as url from 'url'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -29,6 +30,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs b/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs index d24e5d9f20d9..a8b0aa0b7c5d 100644 --- a/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs +++ b/dev-packages/node-integration-tests/suites/anr/basic-multiple.mjs @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/node'; import * as assert from 'assert'; import * as crypto from 'crypto'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -25,10 +26,11 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); -setTimeout(() => { - longWork(); -}, 4000); + // Second blocking event for maxAnrEvents test + setTimeout(() => { + longWork(); + }, 2000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/basic-session.js b/dev-packages/node-integration-tests/suites/anr/basic-session.js index 7971d547c884..8658c465adc9 100644 --- a/dev-packages/node-integration-tests/suites/anr/basic-session.js +++ b/dev-packages/node-integration-tests/suites/anr/basic-session.js @@ -2,6 +2,7 @@ const crypto = require('crypto'); const assert = require('assert'); const Sentry = require('@sentry/node'); +const { waitForDebuggerReady } = require('@sentry-internal/test-utils'); setTimeout(() => { process.exit(); @@ -24,6 +25,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/basic.js b/dev-packages/node-integration-tests/suites/anr/basic.js index 430058200b8f..61b394c630e2 100644 --- a/dev-packages/node-integration-tests/suites/anr/basic.js +++ b/dev-packages/node-integration-tests/suites/anr/basic.js @@ -2,6 +2,7 @@ const crypto = require('crypto'); const assert = require('assert'); const Sentry = require('@sentry/node'); +const { waitForDebuggerReady } = require('@sentry-internal/test-utils'); global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -26,6 +27,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/basic.mjs b/dev-packages/node-integration-tests/suites/anr/basic.mjs index 19b766c1e0e4..20737c93c5f2 100644 --- a/dev-packages/node-integration-tests/suites/anr/basic.mjs +++ b/dev-packages/node-integration-tests/suites/anr/basic.mjs @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/node'; import * as assert from 'assert'; import * as crypto from 'crypto'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; global._sentryDebugIds = { [new Error().stack]: 'aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaa' }; @@ -25,11 +26,11 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); -// Ensure we only send one event even with multiple blocking events -setTimeout(() => { - longWork(); -}, 4000); + // Ensure we only send one event even with multiple blocking events + setTimeout(() => { + longWork(); + }, 2000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/forked.js b/dev-packages/node-integration-tests/suites/anr/forked.js index e0e120f41256..1abed46c7b68 100644 --- a/dev-packages/node-integration-tests/suites/anr/forked.js +++ b/dev-packages/node-integration-tests/suites/anr/forked.js @@ -2,6 +2,7 @@ const crypto = require('crypto'); const assert = require('assert'); const Sentry = require('@sentry/node'); +const { waitForDebuggerReady } = require('@sentry-internal/test-utils'); setTimeout(() => { process.exit(); @@ -25,6 +26,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/node-integration-tests/suites/anr/indefinite.mjs b/dev-packages/node-integration-tests/suites/anr/indefinite.mjs index 927e4e5fc4ad..849e35903e14 100644 --- a/dev-packages/node-integration-tests/suites/anr/indefinite.mjs +++ b/dev-packages/node-integration-tests/suites/anr/indefinite.mjs @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/node'; import * as assert from 'assert'; import * as crypto from 'crypto'; +import { waitForDebuggerReady } from '@sentry-internal/test-utils'; setTimeout(() => { process.exit(); @@ -24,6 +25,6 @@ function longWork() { } } -setTimeout(() => { +waitForDebuggerReady(() => { longWork(); -}, 1000); +}); diff --git a/dev-packages/test-utils/src/anr.ts b/dev-packages/test-utils/src/anr.ts new file mode 100644 index 000000000000..7ad8cb097f30 --- /dev/null +++ b/dev-packages/test-utils/src/anr.ts @@ -0,0 +1,19 @@ +import * as inspector from 'inspector'; + +/** + * Waits for the ANR worker's debugger to be fully ready before executing callback. + * + * The ANR worker creates an InspectorSession and connects to the main thread's debugger. + * We poll inspector.url() to detect when the debugger is active, then wait 200ms for the + * async session setup to complete. + */ +export function waitForDebuggerReady(cb: () => void): void { + const check = (): void => { + if (inspector.url()) { + setTimeout(cb, 200); + } else { + setImmediate(check); + } + }; + setImmediate(check); +} diff --git a/dev-packages/test-utils/src/index.ts b/dev-packages/test-utils/src/index.ts index c47f46fcde5e..aaf4cc1d886a 100644 --- a/dev-packages/test-utils/src/index.ts +++ b/dev-packages/test-utils/src/index.ts @@ -26,3 +26,5 @@ export type { CDPClientOptions } from './cdp-client'; export { MemoryProfiler } from './memory-profiler'; export type { MemoryProfilerOptions, SnapshotStats, SnapshotComparisonResult } from './memory-profiler'; + +export { waitForDebuggerReady } from './anr';