Event Loop Block Detection

Monitor for blocked event loops in Electron applications

Event Loop Block errors, or Application Not Responding (ANR) errors are triggered when the Electron main or renderer processes event loop is blocked for more than the configured threshold. The Electron SDK reports ANR errors as Sentry events and can attach a stack trace of the blocking code to the ANR event.

(Available in version 6.9.0 and above)

Event loop blocked detection can be individually enabled for the main and renderer processes.

Install @sentry/node-native to use the eventLoopBlockIntegration in the main process.

Copied
npm install @sentry/node-native

Copied
import * as Sentry from "@sentry/electron/main";
import { eventLoopBlockIntegration } from "@sentry/electron/native";

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  integrations: [eventLoopBlockIntegration({ threshold: 500 })],
});

Copied
export interface ThreadBlockedIntegrationOptions {
  /**
   * Threshold in milliseconds to trigger an event.
   *
   * Defaults to 1000ms.
   */
  threshold: number;
  /**
   * Maximum number of blocked events to send per clock hour.
   *
   * Defaults to 1.
   */
  maxEventsPerHour: number;
  /**
   * Tags to include with blocked events.
   */
  staticTags: { [key: string]: Primitive };
}

Copied
import * as Sentry from "@sentry/electron/renderer";

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  anrDetection: { captureStackTrace: true },
});

You can pass a configuration object for anrDetection in the renderer to customize the ANR detection behavior.

Copied
interface Options {
  /**
   * Interval to send heartbeat messages to the child process.
   *
   * Main process: Defaults to 50ms.
   * Renderer process: Defaults to 1000ms.
   */
  pollInterval: number;
  /**
   * Threshold in milliseconds to trigger an ANR event.
   *
   * Defaults to 5000ms.
   */
  anrThreshold: number;
  /**
   * Whether to capture a stack trace when the ANR event is triggered.
   *
   * Defaults to `false`.
   */
  captureStackTrace: boolean;
}

In the main process, the eventLoopBlockIntegration uses a native module to track threads and capture stack traces via v8's native APIs. A worker thread is used to capture events even if the main thread is blocked. Overhead with no event loop blocking should be minimal. Each thread notifies the native module that it is alive every threshold / 2 milliseconds. Once an event loop block is detected, v8's native APIs are used to pause all threads and capture stack traces. The pause time is considered inconsequential if the event loop has already been blocked for hundreds of milliseconds.

In the renderer processes, a similar polling mechanism is used to detect event loop blocks. In Electron v34 or newer, the frame.collectJavaScriptCallStack() API is used to capture stack traces when an event loop block is detected. In older Electron versions, the v8 inspector API is used to capture stack traces. The inspector API can have a slight negative impact on performance since it can cause v8 to de-optimize some code paths. For this reason we recommend updating to Electron v34 or newer to use this feature in production.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").