Skip to content

Guide · Open source

How to use winston: create a logger, add transports and levels

Updated · written with AI from the project's own documentation and checked against our catalogue data

winston is a JavaScript logging library for Node.js. It records messages from your program and sends them to one or more destinations called transports, such as the console or a log file. This guide shows how to install it, create a logger, set severity levels and formats, and attach per-request metadata with child loggers.

winstonwinstonjs/winston · ★ 24.5k · MIT

Quick start

  1. 1Install winston. Run npm install winston in your project folder. Node.js must already be installed.
  2. 2Create a logger. Call winston.createLogger with a level, a format and a list of transports.
  3. 3Choose transports. Add a File transport for persistent logs and a Console transport for development output.
  4. 4Set severity levels. Use the level option on each transport so errors go to one file while all logs go elsewhere.
  5. 5Write log messages. Call logger.info, logger.error or logger.log with a message.
  6. 6Add metadata. Use logger.child with an object such as a request ID to tag related messages.

Install winston with npm

winston is installed from npm, so you need Node.js and the npm package manager available on your machine. Run the install command inside your project folder.

  • Requirement: Node.js
  • Package: winston, installed from npm
npm install winston

Create your first logger with transports

The recommended way to use winston is to create your own logger with winston.createLogger. Each transport is a storage target for your logs. In the example, error-level messages go to error.log, and all info-level and higher messages go to combined.log.

The default logger exposed by require('winston') has no transports by default, so you must add transports yourself. Leaving it without transports may produce a high memory usage issue.

  • level sets the lowest importance to log; the default is 'info'.
  • format sets how messages are formatted; the default is winston.format.json.
  • transports lists where logs are sent; the default is no transports.
  • silent set to true suppresses all logs.
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), defaultMeta: { service: 'user-service' }, transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ], }); if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), })); }

Log messages at different levels

winston levels follow the severity ordering specified by RFC5424: lower numbers are more important. The built-in levels are error, warn, info, http, verbose, debug and silly. Each level becomes a convenience method on the logger, and you can also call logger.log with an object that has level and message properties.

  • error: 0
  • warn: 1
  • info: 2
  • http: 3
  • verbose: 4
  • debug: 5
  • silly: 6
logger.log({ level: 'info', message: 'Hello distributed log files!' }); logger.info('Hello again distributed logs');

Add, remove and reconfigure transports

You can add or remove transports after the logger is created. The configure method replaces the existing transports wholesale with the ones in the new configuration.

const files = new winston.transports.File({ filename: 'combined.log' }); const console = new winston.transports.Console(); logger .clear() .add(console) .add(files) .remove(console);

Add per-request metadata with child loggers

A child logger passes metadata overrides from an existing logger. This is useful when you want every message from one request to carry the same identifier. The README warns that .child may be bugged if you also extend the Logger class, so use it with caution in that case.

const childLogger = logger.child({ requestId: '451' });

What people use it for

  • Write error-level messages to a file while sending all messages to the console during development.
  • Keep a service name in every log line with defaultMeta.
  • Create a child logger per request so related messages share a requestId.
  • Define custom log levels for a project that needs its own severity names.

Frequently asked questions

Is winston free to use?

winston is released under the MIT licence, as stated in the project's repository. Check the licence file in the repository for the full terms.

What do I need to install winston?

winston is installed from npm with npm install winston, and the source lists Node.js as the prerequisite. It is a Node.js library and is not documented for browser use.

Can winston run in the browser?

The README describes winston as a Node.js library and does not document browser usage. Use it in server-side Node.js code.

Why are my logs not appearing?

The default logger has no transports, so you need to add at least one transport such as Console or File. Also check the level option, since messages below that level are not logged.

What are the alternatives to winston?

The comparable projects listed for this directory are pino, bunyan and log4js. Compare them on the formats, transports and levels you need.

Does winston provide a hosted log dashboard?

No. winston is a library and does not provide a server or dashboard, so you need a separate service if you want hosted log search.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

winston suits Node.js developers who need file-based or structured application logs, different levels sent to different destinations, or custom formats and transports. If you only need a quick console.log replacement for a tiny script, or a hosted log-search service, pick something else.

Install options & downloads