Koa Bunyan Logger Middleware
raw JSON →Koa-bunyan-logger is a Koa middleware designed for integrating structured logging into Koa v2.x applications, leveraging the popular Bunyan logging library. The current stable version is 2.1.0. While its release cadence has been infrequent, updates typically coincide with significant Koa version shifts or critical bug fixes. This library aims to be flexible and lightweight, allowing applications to customize logging behavior without excessive overhead. A key differentiator is its ability to provide flexible log context, request logging, and explicit support for ignoring specific paths, ensuring that only relevant requests generate log entries. It allows passing an existing Bunyan logger instance or creating a new one with options, and handles request IDs for tracing. It provides middleware specifically for setting request context and logging request/response cycles, including duration and status-based log levels. This package is built on CommonJS but can be imported into ESM projects via interop.
Common errors
error TypeError: app.use is not a function ↓
const app = koa(); to const app = new Koa(); error Application logs appear as raw JSON objects in the console, instead of a human-readable format. ↓
bunyan command-line tool. For example: node your_app.js | npx bunyan -o short. Warnings
breaking Version 2.0.0 and above of `koa-bunyan-logger` are specifically designed for Koa v2.x applications. Attempting to use these versions with Koa v1.x will lead to compatibility issues. ↓
breaking Starting with version 1.2.0, the `req` and `res` objects passed to the logger context changed from Koa's wrapper objects (`this.request`, `this.response`) to the native Node.js HTTP objects (`this.req`, `this.res`). This alters the available properties for logging (e.g., `res.statusCode` instead of `res.status`). ↓
gotcha Koa's default error handler will log raw error stack traces to `stderr` in a non-JSON format, which can interfere with structured logging. It is strongly recommended to disable it. ↓
gotcha `koa-bunyan-logger` uses CommonJS module exports. When used in an ESM project, ensure you use the default import (`import koaBunyanLogger from 'koa-bunyan-logger';`) and access sub-middlewares as properties (`koaBunyanLogger.requestLogger()`), as direct named imports are not supported. ↓
Install
npm install koa-bunyan-logger yarn add koa-bunyan-logger pnpm add koa-bunyan-logger Imports
- koaBunyanLogger wrong
import { koaBunyanLogger } from 'koa-bunyan-logger';correctimport koaBunyanLogger from 'koa-bunyan-logger'; // or in CommonJS: const koaBunyanLogger = require('koa-bunyan-logger'); - requestIdContext wrong
import { requestIdContext } from 'koa-bunyan-logger';correctimport koaBunyanLogger from 'koa-bunyan-logger'; // ... app.use(koaBunyanLogger.requestIdContext()); - requestLogger wrong
import { requestLogger } from 'koa-bunyan-logger';correctimport koaBunyanLogger from 'koa-bunyan-logger'; // ... app.use(koaBunyanLogger.requestLogger());
Quickstart
import Koa from 'koa';
import bunyan from 'bunyan';
import koaBunyanLogger from 'koa-bunyan-logger';
const app = new Koa();
// Create a Bunyan logger instance, which koa-bunyan-logger will use
const appLogger = bunyan.createLogger({
name: 'my-koa-app',
level: 'info',
serializers: bunyan.stdSerializers
});
// Apply the main logging middleware with the custom logger instance
app.use(koaBunyanLogger(appLogger));
// Add middleware for setting a request ID context
app.use(koaBunyanLogger.requestIdContext());
// Add middleware for logging request/response cycles
app.use(koaBunyanLogger.requestLogger({
// Example option: ignore specific paths from detailed request logging
ignorePath: ['/healthcheck', '/metrics']
}));
// Custom application middleware to use the logger in a request context
app.use(async (ctx, next) => {
ctx.log.info('Received request from %s for %s', ctx.request.ip, ctx.path);
await next();
// Note: 'x-response-time' header might need to be set by another middleware if desired
ctx.log.info({ status: ctx.status }, 'Handled request for %s', ctx.path);
});
// Simple route handling
app.use(async (ctx) => {
if (ctx.path === '/healthcheck') {
ctx.body = 'OK';
} else {
ctx.body = 'Hello World';
}
});
// IMPORTANT: Disable Koa's default error handler to prevent raw stack traces
app.on('error', () => {});
const PORT = process.env.PORT ?? 8000;
app.listen(PORT, () => {
console.log(`Server listening on http://localhost:${PORT}`);
console.log('To view structured logs, pipe output to bunyan CLI: node yourfile.js | npx bunyan -o short');
});