patternjavascriptModerate
Winston structured logging: JSON format with custom transports
Viewed 0 times
winston ^3.x
winstonJSON formatformat.combineformat.errorsstack tracedefaultMetastructured loggingchild logger
nodejs
Problem
Winston is configured with the default format which produces human-readable strings. In production, log aggregators cannot parse these strings as structured data, making field-based filtering and querying impossible.
Solution
Configure Winston with JSON format and combine format for consistent structured output.
Note: pino is 5-10x faster than winston in high-throughput scenarios — consider migrating if performance is a concern.
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }), // serialize Error objects with stack traces
winston.format.json()
),
defaultMeta: {
service: 'order-service',
environment: process.env.NODE_ENV,
version: process.env.APP_VERSION,
},
transports: [
new winston.transports.Console(),
// In production, add a transport for your log aggregator
// new WinstonLoki({ host: 'http://loki:3100', labels: { service: 'order-service' } }),
],
});
// Logging with metadata
logger.error('Payment failed', {
orderId: '123',
error: err, // errors({ stack: true }) handles this
userId: req.user.id,
});Note: pino is 5-10x faster than winston in high-throughput scenarios — consider migrating if performance is a concern.
Why
winston.format.errors({ stack: true }) is non-obvious but essential — without it, Error objects logged as metadata are serialized as empty objects {} because JSON.stringify ignores non-enumerable properties like message and stack.
Gotchas
- winston.format.errors() must come before winston.format.json() in the combine() pipeline — order matters
- Without errors({ stack: true }), Error objects in metadata are logged as '{}' — this silently loses stack traces
- defaultMeta is merged into every log entry — avoid putting request-scoped data here; use child loggers instead
- winston does not support child loggers natively — use winston-child-logger package or switch to pino for this feature
Context
Setting up production-grade structured logging with Winston in a Node.js application
Revisions (0)
No revisions yet.