Event Loop Block Detection for Electron

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: "___PUBLIC_DSN___",
  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({
  integrations: [Sentry.eventLoopBlockIntegration({ threshold: 500 })],
});

Copied
interface Options {
  /**
   * Threshold in milliseconds to trigger an event.
   *
   * Defaults to 1000ms.
   */
  threshold: number;
}

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. By default, the v8 inspector API is used to capture stack traces when an event loop block is detected. The inspector API can have a slight negative impact on performance since it can cause v8 to de-optimize some code paths.

To capture stack traces without the inspector API, enable the captureNativeStacktrace option of the rendererEventLoopBlockIntegration in the main process. The SDK then uses the frame.collectJavaScriptCallStack() API to capture stack traces, which avoids the performance impact of the inspector API.

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

Sentry.init({
  dsn: "___PUBLIC_DSN___",
  integrations: [
    Sentry.rendererEventLoopBlockIntegration({
      captureNativeStacktrace: true,
    }),
  ],
});
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").