pino-http
The fastest structured HTTP request logger for Node.js, built directly on pino and ready to drop into any http server or Express app.
Repository Health
Technical Analysis
pino-http wraps a pino logger instance around Node’s raw http.IncomingMessage/ServerResponse cycle, attaching a child logger to every request (req.log) and response (res.log) and automatically emitting a structured completion log when the response finishes, errors, or the connection closes. It benchmarks well ahead of other Node HTTP loggers because it inherits pino’s low-overhead, asynchronous JSON serialization rather than doing synchronous string formatting on the request path.
Beyond the zero-config default, it exposes a deep hook system — customLogLevel, customProps, customSuccessMessage/Object, customErrorMessage/Object, customReceivedMessage/Object, customAttributeKeys, and wrapSerializers — so teams can reshape field names, add request-scoped metadata, or change log levels per status code without forking the library or writing their own middleware from scratch. It works unmodified as vanilla Node middleware or as Express middleware, and integrates with pino’s transport and pretty-printing ecosystem out of the box.
What You Get
- Automatic request/response logging on every request, with no manual log calls required
- A child logger available as req.log / res.log, pre-bound with request context for any additional log lines a handler wants to add
- Configurable log levels per response (customLogLevel) so 4xx/5xx responses can be logged as warn/error automatically
- Custom request ID generation (genReqId) with sane integer-based defaults and support for reusing an existing x-request-id header
- Hooks to reshape the logged object and message text at each lifecycle stage (received, success, error) without losing pino’s serializer wrapping
- Drop-in compatibility with plain Node http servers and Express, plus interop with pino transports and pino-pretty for local development
Common Use Cases
- Adding production-grade structured request logging to an Express or vanilla Node HTTP API with a single middleware line
- Centralizing request/response/error logging format across a service so log aggregators (ELK, Datadog, Loki) can parse a consistent schema
- Elevating error-classed responses (4xx/5xx) to warn/error log levels automatically via customLogLevel for alerting pipelines
- Attaching request-scoped correlation IDs (genReqId) that propagate through req.log for distributed tracing correlation
- Suppressing verbose per-request bindings in high-throughput services via quietReqLogger/quietResLogger while keeping request IDs
Under The Hood
Architecture
pino-http is a single-module (logger.js) middleware factory: calling the exported function normalizes options, creates or reuses a pino instance via wrapChild, and returns a closure that wires per-request state onto the Node req/res objects using two module-level Symbols (startTime, reqObject) to avoid polluting the public object shape. The request lifecycle is handled by loggingMiddleware, which attaches child loggers to req.log/res.log and registers ‘finish’/‘close’/‘error’ listeners on the response; onResFinished computes response time, resolves the log level via customLogLevel, and dispatches to either the error or success object/message providers. The separation between option normalization, logger construction, event wiring, and completion handling is clean for a file of this size, and the closure-based design (rather than a class) keeps per-request state private via symbols instead of exposed instance fields.
Tech Stack
The library ships as plain CommonJS JavaScript (logger.js, deprecations.js) with hand-written TypeScript definitions (index.d.ts) validated separately via tsd rather than being compiled from TypeScript source. Runtime dependencies are minimal and pino-ecosystem-native: pino ^10 for the underlying logger, pino-std-serializers ^7 for req/res/err serialization (wrapped via wrapRequestSerializer/wrapResponseSerializer/wrapErrorSerializer), get-caller-file ^2 to resolve transport caller paths, and process-warning ^5 for deprecation warnings. Tests run on Node’s built-in test runner (node —test) with @matteo.collina/tspl for assertions, coverage via c8, linting via eslint with the neostandard shareable config, and CI wired through GitHub Actions.
Code Quality
test/test.js runs to roughly 1,600 lines and exercises the option surface exhaustively — custom log levels, autoLogging.ignore, customProps as both function and object, wrapSerializers toggling, quietReqLogger/quietResLogger, and custom attribute key remapping — plus a dedicated transport-integration.js test for pino transport interop. Error handling is explicit rather than swallowed: incompatible option combinations (useLevel + customLogLevel) throw immediately rather than silently picking one. There’s no TypeScript source, but the public type surface is independently validated against real usage via tsd and ts-node in the test-types script, which catches type-definition drift that plain unit tests would miss.
API Design The public surface is a single factory function that works with zero configuration (require(‘pino-http’)()) as either a raw http listener call or Express middleware, with no adapter code needed either way. Every stage of the request lifecycle (received, success, error) has both a message hook and an object hook, letting consumers restyle log text or the structured payload independently without losing the underlying serializer wrapping. Advanced consumers get an escape hatch via the exported startTime symbol for manually correcting response-time measurement when pino-http isn’t the first middleware in the chain, and stdSerializers/pinoHttp.logger expose the underlying pino primitives directly rather than hiding them behind a facade.
Used by 12 apps in this directory
paperclip
AI Agents · Automation
The open-source control plane that turns a pile of AI agents into an actual company — with org charts, budgets, heartbeats, and governance.
Refly
AI Development · Automation · No Code Platforms
Build deterministic, versioned agent skills from natural language—run them anywhere from Claude Code to Slack.
Teable
Databases · No Code Platforms
A no-code PostgreSQL database with spreadsheet UX, real-time collaboration, and native AI agents — built for teams that outgrow Airtable.