DEV Community

Alex Spinov
Alex Spinov

Posted on

Winston Has a Free API — Here's How to Build Production Logging in Node.js

Winston is the most popular logging library for Node.js. It supports multiple transports, log levels, formatting, and structured logging for production applications.

Installation

npm install winston
Enter fullscreen mode Exit fullscreen mode

Basic Setup

import winston from "winston";

const logger = winston.createLogger({
  level: "info",
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { service: "my-api" },
  transports: [
    new winston.transports.File({ filename: "error.log", level: "error" }),
    new winston.transports.File({ filename: "combined.log" })
  ]
});

// Console in development
if (process.env.NODE_ENV !== "production") {
  logger.add(new winston.transports.Console({
    format: winston.format.combine(
      winston.format.colorize(),
      winston.format.simple()
    )
  }));
}

export default logger;
Enter fullscreen mode Exit fullscreen mode

Logging

logger.info("Server started", { port: 3000 });
logger.warn("Slow query detected", { query: "SELECT...", duration: 2500 });
logger.error("Database connection failed", { host: "db.example.com", error: err.message });

try {
  await riskyOperation();
} catch (err) {
  logger.error("Operation failed", { error: err });
}
Enter fullscreen mode Exit fullscreen mode

Custom Formats

const myFormat = winston.format.printf(({ level, message, timestamp, ...meta }) => {
  return `${timestamp} [${level}]: ${message} ${Object.keys(meta).length ? JSON.stringify(meta) : ""}`;
});

const logger = winston.createLogger({
  format: winston.format.combine(
    winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
    myFormat
  )
});
Enter fullscreen mode Exit fullscreen mode

Child Loggers

function handleRequest(req) {
  const requestLogger = logger.child({ requestId: req.id, userId: req.user?.id });
  requestLogger.info("Processing request", { path: req.url });
  requestLogger.info("Request completed", { status: 200, duration: 150 });
}
Enter fullscreen mode Exit fullscreen mode

Multiple Transports

const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: "app.log", maxsize: 5242880, maxFiles: 5 }),
    new winston.transports.Http({ host: "log-server.example.com", port: 8080 })
  ]
});
Enter fullscreen mode Exit fullscreen mode

Need to extract or automate web content at scale? Check out my web scraping tools on Apify — no coding required. Or email me at spinov001@gmail.com for custom solutions.

Top comments (0)