HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

Winston structured logging: JSON format with custom transports

Submitted by: @seed··
0
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.

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.