Skip to content

feat(node): Deprecate ANR integration #16832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/astro/src/index.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export {
addEventProcessor,
addIntegration,
amqplibIntegration,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
// eslint-disable-next-line deprecation/deprecation
disableAnrDetectionForCallback,
captureCheckIn,
captureConsoleIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/aws-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ export {
close,
getSentryRelease,
createGetModuleFromFilename,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
// eslint-disable-next-line deprecation/deprecation
disableAnrDetectionForCallback,
consoleIntegration,
httpIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/bun/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ export {
close,
getSentryRelease,
createGetModuleFromFilename,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
// eslint-disable-next-line deprecation/deprecation
disableAnrDetectionForCallback,
consoleIntegration,
httpIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/google-cloud-serverless/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ export {
close,
getSentryRelease,
createGetModuleFromFilename,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
// eslint-disable-next-line deprecation/deprecation
disableAnrDetectionForCallback,
consoleIntegration,
httpIntegration,
Expand Down
1 change: 1 addition & 0 deletions packages/node/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export { localVariablesIntegration } from './integrations/local-variables';
export { modulesIntegration } from './integrations/modules';
export { onUncaughtExceptionIntegration } from './integrations/onuncaughtexception';
export { onUnhandledRejectionIntegration } from './integrations/onunhandledrejection';
// eslint-disable-next-line deprecation/deprecation
export { anrIntegration, disableAnrDetectionForCallback } from './integrations/anr';

export { expressIntegration, expressErrorHandler, setupExpressErrorHandler } from './integrations/tracing/express';
Expand Down
49 changes: 41 additions & 8 deletions packages/node/src/integrations/anr/common.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,77 @@
import type { Contexts, DsnComponents, Primitive, SdkMetadata } from '@sentry/core';

/**
* Configuration options for the ANR (Application Not Responding) integration.
*
* These options control how the ANR detection system monitors the Node.js event loop
* and reports blocking events.
*
* @deprecated The ANR integration has been deprecated. Use `eventLoopBlockIntegration` from `@sentry/node-native` instead.
*/
export interface AnrIntegrationOptions {
/**
* Interval to send heartbeat messages to the ANR worker.
* Interval to send heartbeat messages to the ANR worker thread.
*
* Defaults to 50ms.
* The main thread sends heartbeat messages to the worker thread at this interval
* to indicate that the event loop is still responsive. Lower values provide more
* precise detection but may increase overhead.
*
* @default 50 (milliseconds)
*/
pollInterval: number;

/**
* Threshold in milliseconds to trigger an ANR event.
*
* Defaults to 5000ms.
* When the worker thread doesn't receive a heartbeat message for this duration,
* it considers the main thread to be blocked and triggers an ANR event.
*
* @default 5000 (milliseconds)
*/
anrThreshold: number;

/**
* Whether to capture a stack trace when the ANR event is triggered.
*
* Defaults to `false`.
* When enabled, uses the Node.js inspector API to capture the stack trace
* of the blocking code. This provides more detailed information about what
* caused the ANR but requires the debugger to be enabled.
*
* **Note:** This opens the inspector API and required ports.
*
* This uses the node debugger which enables the inspector API and opens the required ports.
* @default false
*/
captureStackTrace: boolean;

/**
* Maximum number of ANR events to send.
* Maximum number of ANR events to send per application session.
*
* Once this limit is reached, the ANR worker thread will exit to prevent
* sending duplicate events. This helps avoid spamming Sentry with repeated
* ANR events from the same blocking issue.
*
* Defaults to 1.
* @default 1
*/
maxAnrEvents: number;

/**
* Tags to include with ANR events.
* Static tags to include with all ANR events.
*
* These tags will be attached to every ANR event sent by this integration,
* useful for categorizing or filtering ANR events in Sentry.
*/
staticTags: { [key: string]: Primitive };

/**
* @ignore Internal use only.
*
* If this is supplied, stack frame filenames will be rewritten to be relative to this path.
* This is used internally for better stack trace readability.
*/
appRootPath: string | undefined;
}

// eslint-disable-next-line deprecation/deprecation
export interface WorkerStartData extends AnrIntegrationOptions {
debug: boolean;
sdkMetadata: SdkMetadata;
Expand Down
47 changes: 46 additions & 1 deletion packages/node/src/integrations/anr/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const INTEGRATION_NAME = 'Anr';

type AnrInternal = { startWorker: () => void; stopWorker: () => void };

// eslint-disable-next-line deprecation/deprecation
const _anrIntegration = ((options: Partial<AnrIntegrationOptions> = {}) => {
if (NODE_VERSION.major < 16 || (NODE_VERSION.major === 16 && NODE_VERSION.minor < 17)) {
throw new Error('ANR detection requires Node 16.17.0 or later');
Expand Down Expand Up @@ -114,8 +115,45 @@ const _anrIntegration = ((options: Partial<AnrIntegrationOptions> = {}) => {
} as Integration & AnrInternal;
}) satisfies IntegrationFn;

// eslint-disable-next-line deprecation/deprecation
type AnrReturn = (options?: Partial<AnrIntegrationOptions>) => Integration & AnrInternal;

/**
* Application Not Responding (ANR) integration for Node.js applications.
*
* @deprecated The ANR integration has been deprecated. Use `eventLoopBlockIntegration` from `@sentry/node-native` instead.
*
* Detects when the Node.js main thread event loop is blocked for more than the configured
* threshold (5 seconds by default) and reports these as Sentry events.
*
* ANR detection uses a worker thread to monitor the event loop in the main app thread.
* The main app thread sends a heartbeat message to the ANR worker thread every 50ms by default.
* If the ANR worker does not receive a heartbeat message for the configured threshold duration,
* it triggers an ANR event.
*
* - Node.js 16.17.0 or higher
* - Only supported in the Node.js runtime (not browsers)
* - Not supported for Node.js clusters
*
* Overhead should be minimal:
* - Main thread: Only polling the ANR worker over IPC every 50ms
* - Worker thread: Consumes around 10-20 MB of RAM
* - When ANR detected: Brief pause in debugger to capture stack trace (negligible compared to the blocking)
*
* @example
* ```javascript
* Sentry.init({
* dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
* integrations: [
* Sentry.anrIntegration({
* anrThreshold: 5000,
* captureStackTrace: true,
* pollInterval: 50,
* }),
* ],
* });
* ```
*/
export const anrIntegration = defineIntegration(_anrIntegration) as AnrReturn;

/**
Expand All @@ -125,6 +163,7 @@ export const anrIntegration = defineIntegration(_anrIntegration) as AnrReturn;
*/
async function _startWorker(
client: NodeClient,
// eslint-disable-next-line deprecation/deprecation
integrationOptions: Partial<AnrIntegrationOptions>,
): Promise<() => void> {
const dsn = client.getDsn();
Expand Down Expand Up @@ -229,7 +268,13 @@ async function _startWorker(
export function disableAnrDetectionForCallback<T>(callback: () => T): T;
export function disableAnrDetectionForCallback<T>(callback: () => Promise<T>): Promise<T>;
/**
* Disables ANR detection for the duration of the callback
* Temporarily disables ANR detection for the duration of a callback function.
*
* This utility function allows you to disable ANR detection during operations that
* are expected to block the event loop, such as intensive computational tasks or
* synchronous I/O operations.
*
* @deprecated The ANR integration has been deprecated. Use `eventLoopBlockIntegration` from `@sentry/node-native` instead.
*/
export function disableAnrDetectionForCallback<T>(callback: () => T | Promise<T>): T | Promise<T> {
const integration = getClient()?.getIntegrationByName(INTEGRATION_NAME) as AnrInternal | undefined;
Expand Down
1 change: 1 addition & 0 deletions packages/remix/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
addEventProcessor,
addIntegration,
amqplibIntegration,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
disableAnrDetectionForCallback,
captureCheckIn,
Expand Down
2 changes: 2 additions & 0 deletions packages/solidstart/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export {
addEventProcessor,
addIntegration,
amqplibIntegration,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
// eslint-disable-next-line deprecation/deprecation
disableAnrDetectionForCallback,
captureCheckIn,
captureConsoleIntegration,
Expand Down
2 changes: 2 additions & 0 deletions packages/sveltekit/src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ export {
addEventProcessor,
addIntegration,
amqplibIntegration,
// eslint-disable-next-line deprecation/deprecation
anrIntegration,
// eslint-disable-next-line deprecation/deprecation
disableAnrDetectionForCallback,
captureCheckIn,
captureConsoleIntegration,
Expand Down
Loading