DEV Community

Cover image for Creating a custom logger in Node JS using Winston
Ian Kamau
Ian Kamau

Posted on • Edited on

Creating a custom logger in Node JS using Winston

Hello fellow developers,

I am excited to share with you how you can use winston to develop a custom logger for your node js application. This is beginner friendly and anyone can follow.

Let's get started:
Create an empty directory:

mkdir node-logger
cd node-logger
code .
Enter fullscreen mode Exit fullscreen mode

Open the terminal inside the VS code
Initialize package.json:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install express, dotenv, winston and nodemon:

npm install --save-dev express dotenv winston nodemon
Enter fullscreen mode Exit fullscreen mode

create the index.js file:

touch index.js
Enter fullscreen mode Exit fullscreen mode

After creating index.js go to package.json and add the start script inside scripts:

"scripts": {
    "start": "nodemon index.js",
  },
Enter fullscreen mode Exit fullscreen mode

In index.js lets set up the basic server configuration using Express.

const express = require("express");
const dotenv = require("dotenv");
dotenv.config();

const PORT = process.env.PORT || 8000;
const app = express();

app.listen(PORT, ()=>{
  console.log(`listening on http://localhost:${PORT}`)
});
Enter fullscreen mode Exit fullscreen mode

Let us now create the .env file:
touch .env
Now add your environment variables inside your .env file:

PORT=8000
NODE_ENV=development
Enter fullscreen mode Exit fullscreen mode

With that done, in the terminal inside your VS code, create a folder utils and inside utils create a file called logger.js:

mkdir utils
cd utils
touch logger.js
Enter fullscreen mode Exit fullscreen mode

In logger.js, lets write the logging logic. First let us import winston and configure dotenv:

const winston = require("winston");
const dotenv = require("dotenv");
dotenv.config();
Enter fullscreen mode Exit fullscreen mode

Then we will define our security levels:

const levels = {
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  debug: 4,

}

const level = () => {
  const isDevelopment = process.env.NODE_ENV || "development";
  return isDevelopment ? "debug" : "warn";
};
Enter fullscreen mode Exit fullscreen mode

We will define different colors for each level and tell winston to use those colors:

const colors = {
  error: "red",
  warn: "yellow",
  info: "green",
  http: "magenta",
  debug: "white",
};

winston.addColors(colors);
Enter fullscreen mode Exit fullscreen mode

After that, select the aspect of our logging process to customize the log format:

const format = winston.format.combine(
  winston.format.timestamp({
    format: "YYYY-MM-DDTHH:mm:ss",
  }),

  winston.format.colorize({ all: true }),

  winston.format.printf(
    (info) => `${info.timestamp} ${info.level}: ${info.message}`
  )
);
Enter fullscreen mode Exit fullscreen mode

Let's define the transports that the logger must use for printing out messages:

const transports = [
  // Allow the user to console/print the message
  new winston.transports.Console(),
  // Allow to print all error level messages inside the all.log file
  new winston.transports.File({
    filename: "logs/error.log",
    level: "error",
  }),

  // Allow to print all messages inside the all.log file
  new winston.transports.File({
    filename: "logs/all.log",
  }),
];
Enter fullscreen mode Exit fullscreen mode

Configure the transports that the logger needs to employ for displaying messages:

const Logger = winston.createLogger({
  level: level(),
  levels: levels,
  format: format,
  transports: transports,
  exitOnError: false,
});

module.exports = Logger;
Enter fullscreen mode Exit fullscreen mode

In your index.js import logger from logger.js:

const Logger = require("./utils/logger");
Enter fullscreen mode Exit fullscreen mode

replace console.log with Logger.http
Finally, start the server:

npm start
Enter fullscreen mode Exit fullscreen mode

Top comments (0)