This page documents the internal event system, telemetry pipeline, audit log streaming, Prometheus metrics, and Sentry error reporting in packages/cli. These systems capture structured signals about workflow executions, user actions, and system lifecycle for product analytics, operational auditing, and error tracking.
For environment variable configuration that controls these systems (Sentry DSN, diagnostics flags, metrics toggles), see Configuration System. For how workflow execution lifecycle hooks fire these events, see Workflow Execution Lifecycle.
The observability stack is built around a central in-process typed pub/sub bus (EventService) and a relay pattern. Code throughout packages/cli emits events. Relay services independently subscribe to those events and forward them to external sinks.
Diagram: Observability Data Flow
Sources: packages/cli/src/commands/base-command.ts84-186 packages/cli/src/server.ts150-234 packages/cli/src/events/relays/telemetry.event-relay.ts packages/cli/src/events/relays/log-streaming.event-relay.ts
EventService (packages/cli/src/events/event.service.ts) is a typed wrapper over Node's EventEmitter. It is registered as a DI @Service() and injected into any component that needs to emit or subscribe to events.
The type parameter is RelayEventMap (see below), so eventService.emit(name, payload) is fully type-checked at compile time: the payload type is inferred from the event name.
Diagram: EventService and Relay Base Class
Sources: packages/cli/src/events/relays/telemetry.event-relay.ts49-65 packages/cli/src/events/relays/log-streaming.event-relay.ts
packages/cli/src/events/maps/relay.event-map.ts defines RelayEventMap ā the TypeScript type that maps every event name to its strongly typed payload. This file is the authoritative registry of all events that flow through EventService.
| Category | Selected Event Names |
|---|---|
| Lifecycle | server-started, session-started, instance-stopped, instance-owner-setup |
| Workflow | workflow-created, workflow-deleted, workflow-archived, workflow-saved, workflow-pre-execute, workflow-post-execute, workflow-executed |
| Node | node-pre-execute, node-post-execute |
| User | user-signed-up, user-deleted, user-invited, user-updated, user-changed-role, user-logged-in, user-login-failed |
| Credentials | credentials-created, credentials-shared, credentials-updated, credentials-deleted |
| Public API | public-api-invoked, public-api-key-created, public-api-key-deleted |
| Source Control | source-control-settings-updated, source-control-user-started-push-ui, source-control-user-finished-push-ui, source-control-user-pulled-api |
| LDAP | ldap-general-sync-finished, ldap-settings-updated, ldap-login-sync-failed |
| SSO | sso-user-project-access-updated, sso-user-instance-role-updated |
| External Secrets | external-secrets-provider-settings-saved, external-secrets-connection-created, external-secrets-connection-updated, external-secrets-connection-deleted |
| Community Packages | community-package-installed, community-package-updated, community-package-deleted |
| Variables | variable-created, variable-updated, variable-deleted |
| Queue / Scaling | job-enqueued, job-dequeued, job-stalled, job-counts-updated |
| License | license-renewal-attempted, license-community-plus-registered |
| AI | (merged from AiEventMap in ai.event-map.ts) |
RelayEventMap imports and merges AiEventMap from packages/cli/src/events/maps/ai.event-map.ts. AI events (logAiEvent) are emitted in workflow-execute-additional-data.ts via eventService.emit(eventName, payload) during node execution.
Sources: packages/cli/src/events/maps/relay.event-map.ts packages/cli/src/workflow-execute-additional-data.ts534-535
TelemetryEventRelay (packages/cli/src/events/relays/telemetry.event-relay.ts) subscribes to all user- and product-relevant events and forwards them to Segment via the Telemetry class.
Activation: init() is called from BaseCommand.init(). If globalConfig.diagnostics.enabled is false, the method returns immediately without registering any listeners or calling telemetry.init().
packages/cli/src/events/relays/telemetry.event-relay.ts67-69
Event translation: Each private handler translates the internal payload into a Segment track() call with a human-readable name and snake_cased properties:
| Internal Event | Segment Event Name |
|---|---|
workflow-created | "User created workflow" |
workflow-post-execute | "Workflow execution finished" |
user-signed-up | "User signed up" |
credentials-created | "User created credentials" |
community-package-installed | "cnr package install finished" |
server-started | "Instance started" |
license-renewal-attempted | "Instance attempted to refresh license" |
workflowPostExecute handler is the most data-rich. It computes the workflow's node graph using TelemetryHelpers.generateNodesGraph() and determines the final execution status via determineFinalExecutionStatus(). Node graph strings are capped at 24 KB to stay within Segment payload limits:
packages/cli/src/events/relays/telemetry.event-relay.ts41-47
serverStarted handler fires on server-started and sends instance-level diagnostics including n8n version, database type, workflow/credential/user counts, binary data mode, and license plan.
Telemetry (packages/cli/src/telemetry/index.ts) wraps the Segment Node.js analytics SDK. It exposes track() and identify(). The anonymous instance ID serves as the Segment userId, so no PII is transmitted unless explicitly included in event properties.
PostHogClient (packages/cli/src/posthog/index.ts) integrates PostHog for feature flag evaluation. It is initialized in BaseCommand.init() at packages/cli/src/commands/base-command.ts183 and again in Server.configure() at packages/cli/src/server.ts161
Sources: packages/cli/src/events/relays/telemetry.event-relay.ts packages/cli/src/commands/base-command.ts183-185
LogStreamingEventRelay (packages/cli/src/events/relays/log-streaming.event-relay.ts) subscribes to events from RelayEventMap and routes them to MessageEventBus as structured audit log entries.
Activation: init() is called inside Server.configure():
Event naming convention: All audit events are given n8n.audit.* prefixed names:
| Internal Event | Audit Event Name |
|---|---|
workflow-created | n8n.audit.workflow.created |
user-signed-up | n8n.audit.user.signedup |
credentials-created | n8n.audit.credentials.created |
user-logged-in | n8n.audit.user.login.success |
user-login-failed | n8n.audit.user.login.failed |
Each handler calls eventBus.sendAuditEvent({ eventName, payload }) with a structured payload containing userId, _email, _firstName, _lastName, and resource-specific fields.
The @Redactable() decorator is applied to handler methods that include PII fields, enabling automatic field-level redaction based on instance configuration.
Sources: packages/cli/src/events/relays/log-streaming.event-relay.ts packages/cli/src/events/__tests__/log-streaming-event-relay.test.ts23-55
MessageEventBus (packages/cli/src/eventbus/message-event-bus/message-event-bus.ts) is the audit log / log streaming subsystem. It manages configurable output destinations (syslog, webhook, file) and serializes EventMessage objects to them.
Event message types are defined in packages/cli/src/eventbus/event-message-classes/index.ts Each message carries an eventName, timestamp, and structured payload.
Initialization: eventBus.initialize() is called in Server.configure() (packages/cli/src/server.ts232-233).
Diagram: MessageEventBus Internal Flow
Destinations are configured via the Log Streaming settings UI or via the REST API at the controller registered in packages/cli/src/events/events.controller.ts.
Sources: packages/cli/src/server.ts232-234 packages/cli/src/eventbus/event-message-classes/index.ts
PrometheusMetricsService is conditionally initialized in Server.configure() when globalConfig.endpoints.metrics.enable is true:
packages/cli/src/server.ts151-154
It exposes a /metrics endpoint on the main process HTTP server. Queue metrics (active, waiting, completed, failed job counts) are collected by ScalingService on a configurable interval and emitted via eventService.emit('job-counts-updated', ...):
packages/cli/src/scaling/scaling.service.ts543-553
Configuration flags (all under GlobalConfig.endpoints.metrics):
| Config Field | Environment Variable | Description |
|---|---|---|
enable | N8N_METRICS | Enable the /metrics endpoint |
includeDefaultMetrics | N8N_METRICS_INCLUDE_DEFAULT_METRICS | Include Node.js runtime metrics |
includeApiEndpoints | N8N_METRICS_INCLUDE_API_ENDPOINTS | Per-route request counters |
includeCacheMetrics | N8N_METRICS_INCLUDE_CACHE_METRICS | Cache hit/miss counters |
includeMessageEventBusMetrics | N8N_METRICS_INCLUDE_MESSAGE_EVENT_BUS_METRICS | Event bus counters |
includeQueueMetrics | N8N_METRICS_INCLUDE_QUEUE_METRICS | BullMQ job counters |
queueMetricsInterval | N8N_METRICS_QUEUE_METRICS_INTERVAL | Collection interval in seconds |
Sources: packages/cli/src/server.ts151-154 packages/cli/src/scaling/scaling.service.ts530-554 packages/cli/src/commands/base-command.ts84-116
ErrorReporter (packages/core/src/errors/error-reporter.ts) is the singleton service for capturing exceptions in Sentry. It wraps the @sentry/node SDK and is initialized at the very start of BaseCommand.init(), before any other service.
Diagram: ErrorReporter Initialization and Usage
Initialization parameters from globalConfig.sentry:
| Parameter | Config Field |
|---|---|
| Sentry DSN | sentry.backendDsn |
| Environment tag | sentry.environment |
| Server name | sentry.deploymentName |
| Traces sample rate | sentry.tracesSampleRate |
| Profiles sample rate | sentry.profilesSampleRate |
| Event loop block threshold | sentry.eventLoopBlockThreshold |
packages/cli/src/commands/base-command.ts88-116
Enabled Sentry integrations are conditional:
| Integration | Condition |
|---|---|
Express | Always |
Http | Always |
Postgres | globalConfig.database.type === 'postgresdb' |
Redis | Queue mode or Redis cache backend |
Error deduplication: ErrorReporter maintains a Set<string> of SHA hashes of error stack traces (seenErrors) to suppress duplicate reports within a process lifetime.
Release expiration: If the n8n release date is more than 6 weeks old, Sentry submission is disabled and a warning is logged:
packages/core/src/errors/error-reporter.ts51-55
Tracing: When tracesSampleRate > 0, distributed tracing is enabled via the Tracing and SentryTracing classes imported from packages/core/src/observability/.
Sources: packages/core/src/errors/error-reporter.ts packages/cli/src/commands/base-command.ts88-116 packages/cli/src/workflow-runner.ts93 packages/cli/src/scaling/scaling.service.ts158
Diagram: Observability System Startup Order
Sources: packages/cli/src/commands/base-command.ts84-186 packages/cli/src/server.ts150-234
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.