Setup custom logger for node express typescript app using winston, morgan and chalk

Setting up a custom logger for node express typescript server

  1. Setting up Nodejs Express Typescript Server
  2. Setting up a custom logger for node express typescript server
  3. Setup Code Linting in VSCode for Express Typescript Server with Eslint
  4. Configuring Tooling using ESLint, Editorconfig, Prettier and Husky
  5. Setting up React Client from scratch
  6. Configuring Monorepo with yarn workspaces and lerna
  7. Creating REST APIs using Node, Express, Typescript, Mongodb
  8. Configuring Typescript with React

In the last tutorial, we learnt how to setup typescript to a node-express app. Let’s move further, and setup a custom logger for our node-express-typescript app, so that whenever we want to log something in our terminal, we have pretty colored and formatted outputs. We don’t want console.log’s anymore in our application code. So let’s do it and create our custom logger, which also saves logs to a file with all the requests and errors.

For various environments, we might need different levels of logging in our app. To help with this we will use winston that provides levels for our logging. morgan is pretty handy when it comes to logging the request and response headers. We gonna be using chalk, because we want colored messages !

Sounds cool ! let’s get started

Add the following dependencies,

$ npm install --save winston morgan @types/morgan

Once added, let’s configure our logger:

In lib/logger.ts, add the following :

import * as winston from 'winston';

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

const colors = {
    error: "red",
    warn: "yellow",
    info: "green",
    verbose: "gray",
    debug: "blue",
    silly: "grey"
}

const level = () => {
    const env = process.env.NODE_ENV || 'development'
    const isDevelopment = env === 'development'
    return isDevelopment ? 'debug': 'warn'
}

winston.addColors(colors);

const winstonFormat = winston.format.combine(
    winston.format.colorize({
        all: true
    }),
    winston.format.label({
        label: '[LOGGER]'
    }),
    winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms'}),
    winston.format.align(),
    winston.format.printf(
        (info) => `${info.timestamp} ${info.level}: ${info.message}`,
    )
)

const winstonLogger =  winston.createLogger({
    level: level(),
    levels,
    format: winstonFormat,
    transports: [
        new winston.transports.Console(),
        new winston.transports.File({
            filename: 'logs/error.log',
            level: 'error',
        }),
        new winston.transports.File({ filename: 'logs/all.log' }),
    ],
});

export default winstonLogger;

Also, we might need to use our winstonLogger to write logs to a file (to save logs)

What we can do is we can use the winstonLogger and use its output as stream and pass it to
our morgan middleware.

In config/morganMiddleware.ts , add the following :

import * as morgan from 'morgan';
import { isDevelopment } from '../env';
import { logger } from '../lib';

const loggerStream: morgan.StreamOptions = {
    write: (message) =>
        logger.http(message.substring(0, message.lastIndexOf('\n')))
}

const morganMiddleware = morgan(
    ':method :url :status :res[content-length]- :response-time ms - API Server',
    { stream: loggerStream, skip: () => !isDevelopment},
)

export default morganMiddleware;

Also, lets use some colors for our console logs, we will use chalk, update the above file like this:

import chalk from 'chalk';
import * as morgan from 'morgan';
import { isDevelopment } from '../env';
import { logger } from '../lib';

const loggerStream: morgan.StreamOptions = {
    write: (message) =>
        logger.http(message.substring(0, message.lastIndexOf('\n')))
}

const morganMiddleware = morgan(
    chalk.yellow(':method :url :status :res[content-length]- :response-time ms'),
    { stream: loggerStream, skip: () => !isDevelopment},
)

export default morganMiddleware;

Now finally, the logging should happen like this :

Scroll to Top