Express Winston Middleware
express-winston is an Express.js middleware package that integrates the popular Winston logging library into web applications, enabling structured request and error logging. The current stable version is 4.2.0. The project maintains a somewhat active release cadence, frequently addressing dependency updates, security fixes, and minor feature enhancements within the 4.x series. Its key differentiators include extensive configuration options for filtering request/response metadata (e.g., using whitelists and blacklists, though these terms are slated for removal in v5.x), dynamic log levels, and the ability to leverage any of Winston's powerful transports and formatting capabilities directly within the Express middleware stack for both HTTP request logging and centralized error handling.
Common errors
-
TypeError: expressWinston.logger is not a function
cause Attempting to access `logger` directly on `expressWinston` after an incorrect ES module default import or `require` statement that doesn't correctly resolve the module's exports.fixFor ESM, use `import * as expressWinston from 'express-winston';` or `import { logger, errorLogger } from 'express-winston';`. For CommonJS, ensure `const expressWinston = require('express-winston');`. -
Error: Cannot find module 'winston'
cause The `winston` library, a required peer dependency for `express-winston`, is not installed or cannot be found by Node.js.fixInstall `winston` explicitly in your project: `npm install winston@^3.0.0` or `yarn add winston@^3.0.0`. Verify that your `package.json` lists a compatible `winston` version. -
TypeScript compilation error: Property 'logger' does not exist on type 'typeof import("/path/to/node_modules/express-winston/index.d.ts")'cause Incorrect TypeScript import statement, often trying to use a default import for a module that exports named members or a namespace object.fixUse a namespace import: `import * as expressWinston from 'express-winston';` or specifically named imports: `import { logger, errorLogger } from 'express-winston';` to correctly leverage the provided type definitions.
Warnings
- breaking The `metaField` configuration property functionality changed significantly in `v4.0.0`. Existing configurations using `metaField` may behave differently or require updates.
- breaking Upcoming `v5.x` releases will introduce breaking changes by removing or renaming configuration options and types that use terms like `whitelist` and `blacklist`. This is part of a project initiative to update terminology.
- gotcha The project has issued a 'CALL FOR MAINTAINERS', indicating that while current `v4.x` updates are ongoing, the long-term maintenance and future development roadmap may become uncertain without new contributors.
- gotcha Ensure `winston` is installed as a peer dependency with a compatible version (`>=3.x <4`). Mismatched or missing `winston` installations can lead to runtime errors, module not found issues, or unexpected logging behavior.
- gotcha For `express-winston.errorLogger` to function correctly, it must be placed *after* your Express router but *before* any other custom error-handling middleware. Incorrect placement will prevent `express-winston` from catching and logging application errors.
Install
-
npm install express-winston -
yarn add express-winston -
pnpm add express-winston
Imports
- expressWinston
import expressWinston from 'express-winston';
import * as expressWinston from 'express-winston';
- logger, errorLogger
import expressWinston from 'express-winston'; // Then expressWinston.logger
import { logger, errorLogger } from 'express-winston'; - expressWinston
import expressWinston from 'express-winston'; // In CommonJS contexts
const expressWinston = require('express-winston');
Quickstart
import express from 'express';
import winston from 'winston';
import * as expressWinston from 'express-winston';
const app = express();
const logger = winston.createLogger({
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
)
})
]
});
// Request Logger: Logs all incoming HTTP requests
app.use(expressWinston.logger({
winstonInstance: logger,
meta: true, // Log request metadata (ip, url, method, body, etc.)
msg: "HTTP {{req.method}} {{req.url}} {{res.statusCode}} {{res.responseTime}}ms",
colorize: true,
statusLevels: true // Use different log levels based on HTTP status codes
}));
app.get('/', (req, res) => {
res.status(200).send('Hello, World! This is a logged request.');
});
app.get('/error-route', (req, res, next) => {
// Simulate an error
next(new Error('Oops! Something went wrong on this route.'));
});
// Error Logger: Must be placed after the router but before any other error handling middleware
app.use(expressWinston.errorLogger({
winstonInstance: logger,
meta: true, // Log error metadata (stack trace, request info)
msg: "HTTP Error encountered: {{err.message}}",
colorize: true
}));
// Custom error handler (after express-winston.errorLogger)
app.use((err, req, res, next) => {
console.error(`Caught by custom error handler: ${err.message}`);
res.status(500).send('An unexpected error occurred!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
console.log('Try visiting / and /error-route to see logs.');
});