Express Request/Response Logger

raw JSON →
4.0.3 verified Thu Apr 23 auth: no javascript

express-requests-logger is an Express middleware designed for comprehensive logging of incoming HTTP requests and outgoing responses within Node.js applications. The current stable version is 4.0.3, with v4.0.1 released in August 2024, indicating active maintenance though its release cadence can be somewhat irregular. A key differentiator is its extensive configuration options, allowing developers to precisely control what data is logged. This includes masking or excluding sensitive fields from request and response bodies, headers, and query parameters. It also supports integration with custom loggers, although it's primarily tested with Bunyan, and offers a `shouldSkipAuditFunc` for dynamic conditional logging. The `doubleAudit` feature provides flexibility for logging requests both upon arrival and after the response is sent, which can be crucial for debugging systems prone to crashes during request processing.

error TypeError: audit is not a function
cause This error typically occurs when the `express-requests-logger` package is imported incorrectly, treating its default export as a named export.
fix
For ES Modules (ESM), use import audit from 'express-requests-logger';. For CommonJS, use const audit = require('express-requests-logger');.
error Error: logger.info is not a function
cause The object provided to the `logger` option within the `express-requests-logger` configuration does not have a callable `info` method.
fix
Ensure that the logger object passed to the logger option is correctly initialized and exposes an info method, as demonstrated with bunyan.createLogger() in the quickstart example.
error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
cause This is a general Express error, but it can sometimes be triggered or exacerbated by middleware if not handled carefully, especially with `doubleAudit` or custom `shouldSkipAuditFunc` that modifies responses without proper checks.
fix
Ensure that your routes and other middleware do not attempt to send responses or modify headers after res.send(), res.json(), or res.end() has already been called. Always return or use next() after sending a response if subsequent middleware should not execute.
breaking The log message level for HTTP 5xx status codes has been changed from 'info' to 'ERROR'. This means that server-side errors will now be categorized at a higher severity level in your logs.
fix Review your logging system's configuration and alerting rules. If you have specific alerts or filters based on log levels, ensure they correctly capture 'ERROR' level messages for 5xx status codes to avoid missing critical alerts. No code changes are typically required in your application.
breaking Official support for Node.js versions 14 and below has been removed. Running `express-requests-logger` on these older Node.js runtimes is no longer officially supported and may lead to unexpected behavior, compatibility issues, or unpatched vulnerabilities.
fix Upgrade your Node.js runtime environment to version 16 or higher. Node.js 16 is the minimum officially supported version for `express-requests-logger` v4.0.0 and subsequent releases.
gotcha The `logger` option expects an object with an `info` method that accepts a single object argument for structured logging. While primarily tested with Bunyan, custom loggers must conform to this interface.
fix If not using Bunyan, ensure your custom logger provides an `info` method with the signature `(data: object) => void`. You might need to create a simple wrapper function to adapt your logger's API to this expected format.
gotcha Enabling `doubleAudit: true` causes each request and its corresponding response to be logged twice: once when the request arrives and again after the response is sent. This can significantly increase log volume.
fix Be mindful of log volume when using `doubleAudit`. Configure your log aggregation and analysis tools to handle or de-duplicate these entries if necessary. If you only need logging after the full request-response cycle, set `doubleAudit: false`.
npm install express-requests-logger
yarn add express-requests-logger
pnpm add express-requests-logger

This quickstart sets up a basic Express application with `express-requests-logger` to demonstrate request and response logging. It integrates with Bunyan, enables JSON body parsing, configures sensitive data masking for both request and response bodies, excludes specific headers, and utilizes URL exclusion for health check endpoints. It also includes an example of `shouldSkipAuditFunc` for conditional logging.

import express from 'express';
import audit from 'express-requests-logger';
import bunyan from 'bunyan';

const app = express();
const port = 3000;

// Initialize a Bunyan logger for structured logging
const logger = bunyan.createLogger({
  name: 'my-express-app',
  level: 'info' // Set default log level
});

// Add express.json() middleware to parse JSON request bodies
app.use(express.json());

// Apply the express-requests-logger middleware
app.use(audit({
  logger: logger, // Provide the initialized logger
  doubleAudit: true, // Log once on request arrival, and again after response is sent
  excludeURLs: ['/health'], // URLs to entirely skip logging for
  request: {
    maskBody: ['password', 'creditCardNumber'], // Mask sensitive fields in the request body
    excludeHeaders: ['authorization'] // Exclude 'Authorization' header from logs
  },
  response: {
    maskBody: ['jwtToken'], // Mask sensitive fields in the response body
    maxBodyLength: 200 // Limit the length of logged response body content
  },
  shouldSkipAuditFunc: (req, res) => {
    // Example: Skip logging successful responses to /data
    return req.path === '/data' && res.statusCode === 200;
  }
}));

// Define a simple root route
app.get('/', (req, res) => {
  logger.info('Received request for root path.');
  res.status(200).send('Welcome to the API!');
});

// Define a login route to demonstrate body masking
app.post('/login', (req, res) => {
  logger.info('Attempting user login.');
  const { username, password } = req.body;
  if (username === 'test' && password === 'secret') {
    res.status(200).json({ message: 'Login successful', jwtToken: 'a.b.c.123' });
  } else {
    res.status(401).json({ message: 'Invalid credentials' });
  }
});

// Define a health check route (will be excluded from logs)
app.get('/health', (req, res) => {
  res.status(200).send('API is healthy');
});

// Start the Express server
app.listen(port, () => {
  logger.info(`Server listening on port ${port}`);
});