Skip to content

Integrations

Integrations collect logs automatically from platform behavior. They are always opt-in: nothing is captured until you configure the matching integration. Every capture is tagged with source: "integration:<name>" so downstream filtering and loop prevention work.

Privacy guidance for what to enable and how to sanitize lives in OPERATIONS.md.

Runtime Support

RuntimeSupportCountNotes
Browser / frontendFirst-party automatic collectors in @loggerjs/browser19Console, script errors, fetch/XHR, WebSocket, Web Vitals, Performance API, routing, user actions, service worker, extension/Electron renderer hooks, and browser context propagation.
Node.js / serverFirst-party automatic collectors in @loggerjs/node16Process crashes, diagnostics channels, HTTP frameworks, outgoing clients, CLI/serverless lifecycle, queues, and database clients.
Runtime-neutral / coreIntegration API only in @loggerjs/coreThe core package defines the integration contract and loop-prevention helpers, but platform capture lives in the browser and Node.js packages.

Custom integrations should feature-detect their platform surface and no-op when the surface is unavailable.

Stability Levels

Integration stability describes the public setup/options contract and teardown behavior. It does not mean the underlying platform emits every signal in every runtime, browser version, framework version, or deployment mode.

LevelMeaning
StableIntended for v1-compatible application use. Option names, setup/teardown behavior, and high-level captured fields are protected.
CompatiblePublic and tested, but exact field shape or framework/runtime edge handling may still be refined before v1.
Runtime-dependentPublic API is stable, but the signal itself depends on platform support, browser policy, framework hooks, or deployment lifecycle behavior.
IntegrationStabilityWhy
captureConsoleIntegration()StableCore browser capture primitive with loop prevention and teardown coverage.
captureBrowserErrorsIntegration()StableStandard browser error and rejection capture; CSP details vary by browser.
captureFetchIntegration() / captureXHRIntegration()StableRequest/response capture contract is stable with explicit sanitization hooks.
pageLifecycleIntegration()Runtime-dependentAPI is stable, but pagehide/visibility timing is browser-controlled and best effort.
captureWebVitalsIntegration()Runtime-dependentDepends on PerformanceObserver and browser metric support.
capturePerformanceIntegration()Runtime-dependentEntry availability differs by browser, permission policy, and page lifecycle.
captureReportingIntegration()Runtime-dependentReportingObserver and report types vary across browsers.
captureRouterIntegration()StableHistory/hash capture is stable for generic browser routing.
Framework router adaptersCompatiblePublic adapters are tested, but framework-specific hook shapes may evolve.
captureFrameworkErrorsIntegration()CompatiblePublic helper API is stable; framework error hook payloads remain framework-owned.
captureUserActionsIntegration()CompatiblePrivacy-first defaults are stable; element metadata heuristics may be tuned.
captureWebSocketIntegration()CompatibleConstructor patching and event capture are public; sampled message details may evolve.
captureServiceWorkerIntegration()Runtime-dependentDepends on service worker availability and lifecycle messages.
captureRuntimeHostIntegration()Runtime-dependentExtension and Electron surfaces are host-specific and intentionally opt-in by channel.
browserContextPropagationIntegration()StableAmbient context binding contract is stable.
captureProcessIntegration()StableNode crash/warning/exit capture and bounded flush behavior are production commitments.
diagnosticsChannelIntegration()Runtime-dependentNode channel names and payloads come from Node and instrumented libraries.
HTTP framework integrationsCompatibleExpress/Fastify/Koa/Nest/Hapi adapters are public; framework lifecycle details may be tuned.
nodeFetchIntegration() / nodeHttpClientIntegration()CompatibleOutgoing HTTP capture is public; Node/undici/http edge details may evolve.
captureCliIntegration() / serverlessIntegration()CompatibleLifecycle contract is public; platform-specific invocation metadata may be refined.
queueIntegration() / bullMqIntegration()CompatibleGeneric and BullMQ operation capture is public; queue payload metadata is intentionally configurable.
databaseIntegration() / prismaIntegration() / redisIntegration()CompatibleData-client method wrapping is public; statement/command extraction heuristics may evolve.

Import Boundaries

Root package imports are convenience presets. Public integration subpaths are documented so users can choose narrower bundles and so new built-in integrations cannot silently expand the surface without matching docs.

RuntimePublic integration subpaths
Browser@loggerjs/browser/integration-console, @loggerjs/browser/integration-context, @loggerjs/browser/integration-errors, @loggerjs/browser/integration-fetch, @loggerjs/browser/integration-xhr, @loggerjs/browser/integration-framework-errors, @loggerjs/browser/integration-framework-routers, @loggerjs/browser/integration-reporting, @loggerjs/browser/integration-router, @loggerjs/browser/integration-runtime-host, @loggerjs/browser/integration-service-worker, @loggerjs/browser/integration-user-actions, @loggerjs/browser/integration-websocket, @loggerjs/browser/integration-web-vitals, @loggerjs/browser/integration-performance, @loggerjs/browser/integration-page-lifecycle
Node.js@loggerjs/node/integration-process, @loggerjs/node/integration-cli, @loggerjs/node/integration-koa, @loggerjs/node/integration-nest, @loggerjs/node/integration-hapi, @loggerjs/node/integration-prisma, @loggerjs/node/integration-redis, @loggerjs/node/integration-queue, @loggerjs/node/integration-bullmq, @loggerjs/node/integration-serverless, @loggerjs/node/integration-database, @loggerjs/node/integration-express, @loggerjs/node/integration-fastify, @loggerjs/node/integration-fetch, @loggerjs/node/integration-http-client, @loggerjs/node/integration-diagnostics

pnpm verify:component-docs fails when a public integration subpath is exported without being listed here. New entries should also update the stability table above and the runtime validation notes for that integration family.

Browser / Frontend (@loggerjs/browser)

IntegrationCapturesNotes
captureConsoleIntegration()console.debug/info/log/warn/error/trace callsLevel allowlist (levels), rate limit (default 100/s). Patched methods restore on teardown; the console transport writes through unpatched methods, so no loops.
captureBrowserErrorsIntegration()window.onerror script/resource errors, unhandledrejection, optional CSP violationsDeduplicates rapid identical script errors.
captureFetchIntegration()Failed (status ≥ minStatus, default 400) and sampled successful fetch callsHeader allowlists, URL sanitizer. Errors re-throw to the app after capture.
captureXHRIntegration()XMLHttpRequest lifecycle with status and durationSame sanitization options as fetch.
pageLifecycleIntegration()Flushes transports on pagehide / visibilitychangeCoalesces rapid flushes; pair with the HTTP transport's beacon mode.
captureWebVitalsIntegration()CLS, FCP, INP, LCP, TTFBEmits incremental and final values via PerformanceObserver.
capturePerformanceIntegration()navigation, resource, longtask, measure, mark entriesDeduplicated, capped by maxEntries.
captureUserActionsIntegration()clicks, inputs, submitsPer-element throttling; text/value capture is off by default.
captureRouterIntegration()route changes (pushState/replaceState/popstate/hashchange)Optional state normalization.
captureReportingIntegration()ReportingObserver reports (CSP, deprecation, intervention, crash)Drains pending reports on teardown.
captureServiceWorkerIntegration()service worker lifecycle, messages, message errorsMessage data capture off by default.
captureWebSocketIntegration()WebSocket connect/open/close/error and sampled messagesWraps the constructor; sockets created before setup are not tracked.
captureFrameworkErrorsIntegration()React/Vue/Solid/Svelte error hooksExposes reactComponentDidCatch(), vueErrorHandler(), etc.; buffers errors raised before the logger exists (maxPending).
captureRuntimeHostIntegration()browser-extension messages, Electron IPC on configured channelsConservative default: no channels monitored.
browserContextPropagationIntegration()session/request/action and trace contextAdds ambient context providers for traceparent, baggage, session id, request id, and recent user action.
nextRouterIntegration() / reactRouterIntegration() / vueRouterIntegration() / nuxtRouterIntegration()framework router transitionsThin adapters over common router APIs; sanitize URLs before logging.

Node.js / Server (@loggerjs/node)

IntegrationCapturesNotes
captureProcessIntegration()uncaughtException (fatal), unhandledRejection, warnings, exitWith exitOnUncaught, captures a fatal record, calls flushSync(), waits up to flushTimeoutMs for async flush(), then exits with code 1.
diagnosticsChannelIntegration()Node diagnostics_channel messages (http, undici, custom channels)Message payload capture off by default.
expressIntegration(logger)request completion with status, route, duration, request idReturns an Express middleware; optional withContext binding per request.
fastifyIntegration(logger)request lifecycle via onRequest/onError/onResponse hooksReturns a Fastify plugin; state keyed in a WeakMap.
nodeFetchIntegration()outgoing fetch calls with status and durationErrors re-throw after capture.
nodeHttpClientIntegration()http.request / http.get calls
captureCliIntegration()CLI start, exit code, SIGINT/SIGTERMSanitizes argv for token/password/secret patterns.
serverlessIntegration(logger, handler)wraps a serverless handler: invocation, duration, cold start, errorsSupports promise, callback, and sync handlers.
queueIntegration()queue client operations (publish/consume/ack/nack) with durationPatches the methods you list per client.
databaseIntegration()database client calls (query/execute/...) with statement and durationStatement extracted from the first string arg or .sql/.text/.query properties.
koaIntegration() / nestMiddlewareIntegration() / hapiIntegration()framework request lifecycleThin adapters for Koa, Express-compatible Nest middleware, and Hapi request hooks. The Nest adapter does not hook Nest exception filters, interceptors, guards, or the original thrown Error.
prismaIntegration()Prisma raw-query methodsWraps $queryRaw / $executeRaw raw-query variants only. It does not subscribe to $on("query") and does not capture typed model operations such as prisma.user.findMany().
redisIntegration()Redis command methodsCaptures selected command methods, duration, errors, and optional payload metadata.
bullMqIntegration()BullMQ Queue method callsWraps add, addBulk, and a legacy process method when present. It does not hook Worker or QueueEvents lifecycle events such as completed, failed, or stalled.

Context manager

Not an integration, but installed the same way once at startup:

ts
import { installAsyncLocalStorageContext } from "@loggerjs/node";
installAsyncLocalStorageContext();

After this, withContext() values follow async execution across await boundaries.

Writing a Custom Integration

ts
import type { Integration } from "@loggerjs/core";

export function captureThingIntegration(): Integration {
  return {
    name: "thing",
    setup(api) {
      const original = thing.onEvent;
      const capture = api.guard((payload: unknown) => {
        api.capture({
          level: "info",
          message: "thing event",
          data: { payload },
        });
      });

      thing.onEvent = (payload) => {
        capture(payload);
        return original(payload);
      };

      return () => {
        thing.onEvent = original;
      };
    },
  };
}

The setup context (api) gives you:

  • capture(input) — the main entry point; stamps source: "integration:thing".
  • log/trace/debug/info/warn/error/fatal/event/captureException — direct logging methods when capture semantics do not fit.
  • guard(fn) — wraps a callback with a re-entrancy counter. If your patched surface is itself triggered by the logging pipeline (the classic case: console capture + console transport), the recursive invocation is dropped and counted in meta (integration.dropped.reentrant) instead of recursing.
  • unpatched — registry of original console.* / fetch / XMLHttpRequest implementations, shared across all integrations so double patching composes.
  • flush/flushSync/close — for lifecycle-driven integrations like page hide.

Rules of the road:

  • Always return a teardown that restores what you patched. Teardowns run once, in reverse setup order, on logger.close().
  • Setup is idempotent per integration instance; creating two instances patches twice. Export a factory and document it.
  • Degrade gracefully: feature-detect the platform surface and no-op when it is missing.
  • Capture raw structured data and let processors redact; do not pre-format messages.

Released under the MIT License.