Logging with Winston

Node js 8 min min read Updated: Mar 30, 2026 Advanced
Logging with Winston
Advanced Topic 6 of 10

Logging with Winston in Node.js

Logging is a critical part of backend development. It helps developers track application behavior, debug issues, monitor performance, and understand what is happening in production systems.

While simple console.log() statements may work during development, they are not suitable for production environments. This is where Winston comes in. Winston is a powerful logging library for Node.js that allows structured, configurable, and scalable logging.

Key Concept: Winston provides structured logging with levels, formats, and multiple transports for production-ready applications.

What is Winston?

Winston is a popular logging library for Node.js that supports multiple log levels, customizable formats, and different output destinations (called transports).

It allows you to store logs in files, console, or even external systems like log management tools.

Why Use Winston Instead of console.log?

  • Structured logging: Logs are organized and easy to analyze
  • Log levels: Different severity levels like info, error, warn
  • Multiple outputs: Logs can be saved to files, console, or remote services
  • Better debugging: Helps track issues in production
  • Scalable: Suitable for large applications

Installing Winston

Install Winston using npm:

bash npm install winston

Basic Winston Logger Setup

Create a simple logger:

javascript const winston = require("winston"); const logger = winston.createLogger({ level: "info", format: winston.format.json(), transports: [ new winston.transports.Console() ] }); logger.info("Application started"); logger.error("Something went wrong");

In this example:

  • level defines the minimum log level
  • format defines how logs are structured
  • transports define where logs are stored

Log Levels in Winston

Winston supports different log levels based on severity:

  • error – Critical issues
  • warn – Warning messages
  • info – General information
  • http – HTTP request logs
  • verbose – Detailed logs
  • debug – Debugging information
  • silly – Very detailed logs

You can control which logs are recorded by setting the log level.

Logging to Files

In production, logs are often saved to files:

javascript const logger = winston.createLogger({ level: "info", format: winston.format.json(), transports: [ new winston.transports.File({ filename: "error.log", level: "error" }), new winston.transports.File({ filename: "combined.log" }) ] });

This setup:

  • Stores error logs in error.log
  • Stores all logs in combined.log

Logging to Console and File Together

You can combine multiple transports:

javascript const logger = winston.createLogger({ level: "info", format: winston.format.simple(), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: "app.log" }) ] });

Custom Log Format

Winston allows you to customize how logs appear:

javascript const { combine, timestamp, printf } = winston.format; const logFormat = printf(({ level, message, timestamp }) => { return `${timestamp} [${level}]: ${message}`; }); const logger = winston.createLogger({ format: combine( timestamp(), logFormat ), transports: [new winston.transports.Console()] });

This adds timestamps and formats logs in a readable way.

Logging HTTP Requests

You can log incoming HTTP requests in Express:

javascript app.use((req, res, next) => { logger.info(`${req.method} ${req.url}`); next(); });

This helps track API usage and debug request-related issues.

Using Winston in a Separate File

For better structure, you can create a separate logger file:

javascript // logger.js const winston = require("winston"); const logger = winston.createLogger({ level: "info", format: winston.format.json(), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: "app.log" }) ] }); module.exports = logger;

Then use it in your application:

javascript const logger = require("./logger"); logger.info("Server started");

Logging Errors

Winston can be used to log application errors:

javascript try { throw new Error("Something went wrong"); } catch (error) { logger.error(error.message); }

Benefits of Structured Logging

Structured logs (JSON format) make it easier to analyze logs using tools like Elasticsearch, Logstash, and Kibana (ELK stack).

This is especially useful in large-scale applications and microservices architecture.

Best Practices for Logging

  • Use appropriate log levels
  • Avoid logging sensitive data like passwords or tokens
  • Use structured logs (JSON) for production
  • Store logs in files or external systems
  • Monitor logs regularly
  • Rotate log files to avoid large file sizes

Common Mistakes

  • Using console.log in production
  • Logging too much unnecessary data
  • Not separating error logs
  • Not using proper log levels
  • Ignoring log monitoring

Real-World Use Cases

  • Debugging production issues
  • Tracking API requests
  • Error monitoring
  • Security auditing
  • Performance tracking

Conclusion

Winston is a powerful logging solution for Node.js applications. It helps developers manage logs efficiently, making debugging and monitoring much easier in production environments.

By using structured logging, multiple transports, and proper log levels, you can build a reliable and scalable logging system for your application.

Quick Summary: Winston provides structured and scalable logging in Node.js with support for log levels, custom formats, and multiple output destinations.

Get Newsletter

Subscibe to our newsletter and we will notify you about the newest updates on Edugators