Getting started

Installation

Install the package, pick an entry point, and know which runtimes it runs on.

npm install @unhingged/logit
# or
bun add @unhingged/logit
# or
pnpm add @unhingged/logit

The package has no dependencies and ships ESM and CommonJS builds with TypeScript declarations. It is MIT licensed.

Entry points#

One package, five entry points. The root is isomorphic; the others import Node built-ins and are only loaded where you import them.

ImportWhat it addsRuns on
@unhingged/logitThe logger, templates, capture, LogContext, enrichers, filters, formatters, the console / stream / memory / callback / HTTP / Seq sinksNode, Bun, Deno, the Next.js edge runtime, browsers
@unhingged/logit/nodefileSink, withMachineName, withProcessId, withProcessInfo, interceptConsole, closeOnExit — plus everything in the rootNode, Bun
@unhingged/logit/nextwithLogging, createOnRequestError, requestDiagnostics — plus everything in the rootNext.js (Node and edge runtimes)
@unhingged/logit/expressrequestLogger, errorLogger — plus everything in the rootNode, Bun
@unhingged/logit/otelotlpHttpSink, otelBridgeSink, encodeOtlpLogs — plus everything in the rootAnywhere with fetch

Every subpath re-exports the root, so a Node application needs one import:

import { configure, consoleSink, fileSink, closeOnExit, log } from '@unhingged/logit/node';

Runtimes#

  • Node.js 20.16+ — the ambient context (LogContext) rides on AsyncLocalStorage, found through process.getBuiltinModule without a node: import in the root entry. Node 22 and 24 are the targets; 20.16 is the floor.
  • Bun and Deno — the same path; both expose AsyncLocalStorage.
  • Next.js edge runtime — @unhingged/logit/next imports AsyncLocalStorage from node:async_hooks, which the edge runtime provides, and installs it. Use that entry in middleware.ts.
  • Browsers — the root entry works as is. There is no AsyncLocalStorage, so LogContext falls back to a synchronous stack: properties pushed in a callback are visible inside it, not across await. See Browser.

TypeScript#

Types come with the package. The using keyword for LogContext.push() and Operation needs TypeScript 5.2+ with "lib": ["esnext"] (or "esnext.disposable"); without it, call .dispose() / .abandon() yourself.

import type { LogEvent, Sink, Enricher, Filter, LoggerOptions } from '@unhingged/logit';

The quick start gets a logger writing in a few lines. If you are coming from Serilog, For Serilog users maps every API you know. From pino or winston: migrating from pino, migrating from winston.