Log Activity in Node Application

Get the source code from here.

Introduction

As a developer, you have to spend quality time for monitoring, troubleshooting, and debugging. Logging makes it super easy, fast and makes these process smoother.

Logging is a perfect way to keep application events records.

This article has two sections,

Add a logger to your existing application

And also,

Start your application with logger from scratch.

Objectives

  • Logging activity in the node app.

  • Create a specific log file every hour

  • Easy configure log file round (Hourly, daily)

  • Easily configure the log file size

  • Delete log files after specific days

  • Environment specific log structure

Prerequisites

  • Make sure you have already installed node

    If you already have a project and want to integrate logger, just skip the following section Start From Scratch.

We are using winston and winston-daily-rotate-file module here.

Start From Scratch

* If you want to add the logger to an existing application, skip this section and check the next section.**

Create an application directory Node-Application-Logger and enter the directory.

mkdir Node-Application-Logger
cd Node-Application-Logger

Create a node application

npm init -y

Install the dependencies

npm i express morgan winston@3.1.0 winston-daily-rotate-file@3.5.1

Create two files named logger.js and example.js

Your project structure should be followed

├── …
├──Node-Application-Logger
│ ├── example.js
│ ├── logger.js
│ └── package.json
├── …

In your logger.js add the following code

const { createLogger, format, transports } = require('winston');
require('winston-daily-rotate-file');
const fs = require('fs');
const path = require('path');

const env = process.env.NODE_ENV || 'development';
const logDir = 'log';
const datePatternConfiguration = {
  default: 'YYYY-MM-DD',
  everHour: 'YYYY-MM-DD-HH',
  everMinute: 'YYYY-MM-DD-THH-mm',
};
numberOfDaysToKeepLog = 30;
fileSizeToRotate = 1; // in megabyte

// Create the log directory if it does not exist
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir);
}

const dailyRotateFileTransport = new transports.DailyRotateFile({
  filename: `${logDir}/%DATE%-results.log`,
  datePattern: datePatternConfiguration.everHour,
  zippedArchive: true,
  maxSize: `${fileSizeToRotate}m`,
  maxFiles: `${numberOfDaysToKeepLog}d`
});

const logger = createLogger({
  // change level if in dev environment versus production
  level: env === 'development' ? 'verbose' : 'info',
  handleExceptions: true,
  format: format.combine(
    format.label({ label: path.basename(module.parent.filename) }),
    format.timestamp({
      format: 'YYYY-MM-DD HH:mm:ss',
    }),
    format.printf(info => `${info.timestamp}[${info.label}] ${info.level}: ${JSON.stringify(info.message)}`),
  ),
  transports: [
    new transports.Console({
      level: 'info',
      handleExceptions: true,
      format: format.combine(
        format.label({ label: path.basename(module.parent.filename) }),
        format.colorize(),
        format.printf(
          info => `${info.timestamp}[${info.label}] ${info.level}: ${info.message}`,
        ),
      ),
    }),
    dailyRotateFileTransport,
  ],
});

logger.stream = {
  write: (message) => {
    logger.info(message);
  },
};

module.exports = logger;

Your logger the configuration is completed. Now invoke the logger from the following example.js

const express = require('express');
const morgan = require('morgan');
const logger = require('./logger');

const app = express();

logger.error('Error log example');
logger.warn('Warn log example');
logger.info('Info log example');

app.use(morgan('tiny', { stream: logger.stream }));

app.use('/', (req, res) => res.send('Hello World'));

app.listen(3000);

Run your application by

node example.js

You will see a log file root_directory/log

You also have a server on port 3000.

Go to [http://localhost:3000](localhost:3000) and check the updated log file in root_directory/log

Add Logger to Your Existing Application

To add logger, in your existing app, install the dependencies

npm i winston@3.1.0 winston-daily-rotate-file@3.5.1

Now create a config file logger.js and include the code

const { createLogger, format, transports } = require('winston');
require('winston-daily-rotate-file');
const fs = require('fs');
const path = require('path');

const env = process.env.NODE_ENV || 'development';
const logDir = 'log';
const datePatternConfiguration = {
  default: 'YYYY-MM-DD',
  everHour: 'YYYY-MM-DD-HH',
  everMinute: 'YYYY-MM-DD-THH-mm',
};
numberOfDaysToKeepLog = 30;
fileSizeToRotate = 1; // in megabyte

// Create the log directory if it does not exist
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir);
}

const dailyRotateFileTransport = new transports.DailyRotateFile({
  filename: `${logDir}/%DATE%-results.log`,
  datePattern: datePatternConfiguration.everHour,
  zippedArchive: true,
  maxSize: `${fileSizeToRotate}m`,
  maxFiles: `${numberOfDaysToKeepLog}d`
});

const logger = createLogger({
  // change level if in dev environment versus production
  level: env === 'development' ? 'verbose' : 'info',
  handleExceptions: true,
  format: format.combine(
    format.label({ label: path.basename(module.parent.filename) }),
    format.timestamp({
      format: 'YYYY-MM-DD HH:mm:ss',
    }),
    format.printf(info => `${info.timestamp}[${info.label}] ${info.level}: ${JSON.stringify(info.message)}`),
  ),
  transports: [
    new transports.Console({
      level: 'info',
      handleExceptions: true,
      format: format.combine(
        format.label({ label: path.basename(module.parent.filename) }),
        format.colorize(),
        format.printf(
          info => `${info.timestamp}[${info.label}] ${info.level}: ${info.message}`,
        ),
      ),
    }),
    dailyRotateFileTransport,
  ],
});

logger.stream = {
  write: (message) => {
    logger.info(message);
  },
};

module.exports = logger;

Use logger to your application by the import logger.js

const logger = require(‘./logger’);
logger.info(‘Info log example’);

Morgan Integration

To integrate your logger in your node application, use

const express = require('express');

const morgan = require('morgan');

const logger = require('./logger');

const app = express();

app.use(morgan('tiny', { stream: logger.stream }));

Now morgan log will be added in your log file.

Configure

Twist your log configuration in logger.js file.

Update log directory name by updating logDir variable

You can create a separate log file, every hour or every day

Update log daily or hourly by updating datePatternConfiguration variable

Configure how many days log you want to keep

Update the existing log files by date by updating numberOfDaysToKeepLog variable

Configure log file size

Create log file after exceeding certain size by updating*fileSizeToRotate* variable

Conclusion

Hope you can add logger in your existing node application and also use the logger from scratch.

Stay tuned and if there is a confusing term or something, the response below. I will replay ASAP.