# 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](https://medium.com/@bmshamsnahid/node-101-install-and-get-started-with-node-js-8442dea963a4)
> 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.

* To learn more about [Winston](https://www.npmjs.com/package/winston)

* To learn more about [Winston-Daily-Rotate-File](https://www.npmjs.com/package/winston-daily-rotate-file)

## 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

```javascript
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`

```javascript
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`](http://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

```javascript
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.
