From 5446098653e394de42d20a70972529d8aca62c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Ovejero?= Date: Wed, 4 Feb 2026 11:39:18 +0100 Subject: [PATCH] perf(core): Make event loop block detection configurable (#25291) --- .../@n8n/config/src/configs/sentry.config.ts | 10 ++++++++++ packages/@n8n/config/test/config.test.ts | 1 + packages/cli/src/commands/base-command.ts | 11 +++++++++-- packages/core/src/errors/error-reporter.ts | 18 +++++++++++++----- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/@n8n/config/src/configs/sentry.config.ts b/packages/@n8n/config/src/configs/sentry.config.ts index c9169df48ba..12cbb1385a8 100644 --- a/packages/@n8n/config/src/configs/sentry.config.ts +++ b/packages/@n8n/config/src/configs/sentry.config.ts @@ -35,6 +35,16 @@ export class SentryConfig { @Env('N8N_SENTRY_PROFILES_SAMPLE_RATE', sampleRateSchema) profilesSampleRate: number = 0; + /** + * Threshold in milliseconds for event loop block detection. + * When the event loop is blocked for longer than this threshold, + * Sentry will report it. + * + * @default 500 + */ + @Env('N8N_SENTRY_EVENT_LOOP_BLOCK_THRESHOLD', z.number({ coerce: true }).int().positive()) + eventLoopBlockThreshold: number = 500; + /** * Environment of the n8n instance. * diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index 9875fb6516c..45ca584ad77 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -285,6 +285,7 @@ describe('GlobalConfig', () => { deploymentName: '', profilesSampleRate: 0, tracesSampleRate: 0, + eventLoopBlockThreshold: 500, }, logging: { level: 'info', diff --git a/packages/cli/src/commands/base-command.ts b/packages/cli/src/commands/base-command.ts index 2f22d5deb0f..7cac138a274 100644 --- a/packages/cli/src/commands/base-command.ts +++ b/packages/cli/src/commands/base-command.ts @@ -84,8 +84,14 @@ export abstract class BaseCommand { this.dbConnection = Container.get(DbConnection); this.errorReporter = Container.get(ErrorReporter); - const { backendDsn, environment, deploymentName, profilesSampleRate, tracesSampleRate } = - this.globalConfig.sentry; + const { + backendDsn, + environment, + deploymentName, + profilesSampleRate, + tracesSampleRate, + eventLoopBlockThreshold, + } = this.globalConfig.sentry; await this.errorReporter.init({ serverType: this.instanceSettings.instanceType, dsn: backendDsn, @@ -94,6 +100,7 @@ export abstract class BaseCommand { serverName: deploymentName, releaseDate: N8N_RELEASE_DATE, withEventLoopBlockDetection: true, + eventLoopBlockThreshold, tracesSampleRate, profilesSampleRate, eligibleIntegrations: { diff --git a/packages/core/src/errors/error-reporter.ts b/packages/core/src/errors/error-reporter.ts index bf1305fcbd8..069848555dc 100644 --- a/packages/core/src/errors/error-reporter.ts +++ b/packages/core/src/errors/error-reporter.ts @@ -23,6 +23,9 @@ type ErrorReporterInitOptions = { /** Whether to enable event loop block detection, if Sentry is enabled. */ withEventLoopBlockDetection: boolean; + /** Threshold in ms for event loop block detection. Only used if `withEventLoopBlockDetection` is true. */ + eventLoopBlockThreshold?: number; + /** Sample rate for Sentry traces (0.0 to 1.0). 0 means disabled */ tracesSampleRate: number; @@ -107,6 +110,7 @@ export class ErrorReporter { serverName, releaseDate, withEventLoopBlockDetection, + eventLoopBlockThreshold, profilesSampleRate, tracesSampleRate, eligibleIntegrations = {}, @@ -174,10 +178,13 @@ export class ErrorReporter { const eventLoopBlockIntegration = withEventLoopBlockDetection ? // The EventLoopBlockIntegration doesn't automatically include the // same tags, so we set them explicitly. - await this.getEventLoopBlockIntegration({ - server_name: serverName, - server_type: serverType, - }) + await this.getEventLoopBlockIntegration( + { + server_name: serverName, + server_type: serverType, + }, + eventLoopBlockThreshold, + ) : []; const profilingIntegration = isProfilingEnabled ? await this.getProfilingIntegration() : []; @@ -312,11 +319,12 @@ export class ErrorReporter { if (tags) event.tags = { ...event.tags, ...tags }; } - private async getEventLoopBlockIntegration(tags: Record) { + private async getEventLoopBlockIntegration(tags: Record, threshold?: number) { try { const { eventLoopBlockIntegration } = await import('@sentry/node-native'); return [ eventLoopBlockIntegration({ + ...(threshold ? { threshold } : {}), staticTags: tags, }), ];