HTTP request logger middleware for node.js
Morgan is an HTTP request logger middleware for Node.js applications, most commonly used with Express.js. It automatically captures and logs details about incoming HTTP requests and their corresponding responses, including method, URL, status code, response time, and content length. With over 8 million weekly downloads, it's a standard tool in the Node.js ecosystem for monitoring and debugging web applications.
The package operates by inserting itself into the request/response pipeline as middleware. When a request arrives, Morgan captures timing data and request details. When the response completes, it compiles the log entry using either predefined formats (like 'combined' or 'dev') or custom token-based templates. This approach provides minimal overhead while giving developers visibility into application traffic patterns and performance characteristics.
Morgan is particularly valued for its simplicity and flexibility. Developers can start with a single line of code using built-in formats for development, then customize logging behavior with tokens, filtering functions, and output streams for production environments. It supports writing logs to files, stdout, or any writable stream, and allows multiple logger instances to handle different log types simultaneously (for example, all requests to a file while errors go to the console).
The package is maintained as part of the Express.js ecosystem and follows semantic versioning. Its stable API and focused scope—logging HTTP requests only, not general application logging—make it a reliable choice for developers who need straightforward request monitoring without the complexity of full-featured logging frameworks.
const express = require('express');
const morgan = require('morgan');
const fs = require('fs');
const path = require('path');
const app = express();
// Development: color-coded console logs
if (process.env.NODE_ENV !== 'production') {
app.use(morgan('dev'));
}
// Production: JSON logs to file
if (process.env.NODE_ENV === 'production') {
const accessLogStream = fs.createWriteStream(
path.join(__dirname, 'access.log'),
{ flags: 'a' }
);
morgan.token('req-body', (req) => JSON.stringify(req.body));
morgan.token('request-id', (req) => req.headers['x-request-id'] || '-');
app.use(morgan((tokens, req, res) => {
return JSON.stringify({
timestamp: new Date().toISOString(),
requestId: tokens['request-id'](req, res),
method: tokens.method(req, res),
url: tokens.url(req, res),
status: tokens.status(req, res),
responseTime: tokens['response-time'](req, res),
contentLength: tokens.res(req, res, 'content-length'),
userAgent: tokens['user-agent'](req, res)
});
}, { stream: accessLogStream }));
}
// Error-only logging to console
app.use(morgan('combined', {
skip: (req, res) => res.statusCode < 400
}));
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});
app.get('/api/slow', (req, res) => {
setTimeout(() => res.json({ data: 'slow response' }), 2000);
});
app.listen(3000, () => console.log('Server running on port 3000'));Development debugging: Use the 'dev' format during local development to get color-coded, concise logs showing request method, URL, status code, and response time. This helps quickly identify slow endpoints or failing requests without cluttering the console.
Production request auditing: Log all incoming requests to rotating log files using the 'combined' format (Apache-style logs) with a file stream. This creates a permanent audit trail for compliance, security analysis, or traffic pattern investigation.
Performance monitoring: Create custom tokens to log response times and request sizes, then filter logs to only capture requests exceeding a time threshold. This helps identify performance bottlenecks without logging every single request in high-traffic applications.
Error-specific logging: Use the skip option to log only requests that result in 4xx or 5xx status codes, reducing log volume while maintaining visibility into application errors. Combine with a separate logger instance for successful requests to implement split logging strategies.
API analytics: Define custom tokens to extract and log API-specific data like request IDs, client versions from headers, or authenticated user information. Output logs as JSON for easy ingestion into analytics platforms like ELK stack or cloud logging services.
npm install morganpnpm add morganbun add morgan