Logging in Node.js is one of the most important and useful steps a developer can take when working in Node.js. It is one of the most useful steps for a developer in any case of their runtime environment. Logging in Node.js helps developers know what it is that their code is actually doing. Logging in Node.js can help developers save hours of debugging work. The basic purpose of logging is to save information about each flow or runtime. The developer uses this information to understand their application. For instance, if a bug is present in the database section of an app, a log points to the place of failure that helps you to identify the cause of the problem.

Also Read: Node js on hosting: Best Hosting Platforms for 2021

Logging in Node.js

You should remember that not all information need to be logged. For instance, personal data such as delicate data, user information, passwords and credit card information. It is also necessary to remember that the tool you are using to log is less important in comparison to your approach to logging. Let’s discuss some of the most effective approaches as part of Logging in Node.js.

Start with console.log

There is an argument that it should be a regular practice  to have console.log around your applications when building a side-project. There are some other console methods such as console.groupconsole.info, and other less common methods include console.error:

console.error('Error!');

While running console.log, there is chance that you will notice a negligible decrease in performance. We recommend you switching to a logging library when your project starts to expand so that you can avoid negatively impacting performance.

Move to a log library

The developers use logging libraries to create and manage log events. It increases overall efficiency and functionality of your application. Few examples of logging libraries for Node are  WinstonBunyan, and Log4js. Winston will be the best choice if you want to store your error log in a remote location or different database. This is because it can support multiple transports. Bunyan also has the ability to support multiple transports and comes with a CLI for filtering. Log4js is an alternative option that supports log streams, such as logging to a console, and log aggregators like Loggly (using an appended).

You can set up a logging library using Winston with the help of below-mentioned example:

const winston = require('winston');
const config = require('./config');

const enumerateErrorFormat = winston.format((info) => {
  if (info instanceof Error) {
    Object.assign(info, { message: info.stack });
  }
  return info;
});

const logger = winston.createLogger({
  level: config.env === 'development' ? 'debug' : 'info',
  format: winston.format.combine(
    enumerateErrorFormat(),
    config.env === 'development' ? winston.format.colorize() : winston.format.uncolorize(),
    winston.format.splat(),
    winston.format.printf(({ level, message }) => `${level}: ${message}`)
  ),
  transports: [
    new winston.transports.Console({
      stderrLevels: ['error'],
    }),
  ],
});

module.exports = logger;

Here you should remember that you can always use a standard console.log but a logging library can be more functional and it will also help in avoiding decreases in app performance.

Log HTTP requests in Node with Morgan

Logging your HTTP request in your Node.js application is another best practice. The most popular tool for accomplishing this is Morgan. It has the ability to get the server logs and systematizes them to make them more readable.

You just have to set the following format string for using Morgan:

morgan = require('morgan');
app.use(morgan('dev'));

The predefined format string for reference is as follows:

morgan('tiny')

The expected amount is shown in the image below:

Logging in Node.js

Configure Winston with Morgan

If you are using the Winston library then you can easily configure with Morgan as follows:

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

morgan.token('message', (req, res) => res.locals.errorMessage || '');

const getIpFormat = () => (config.env === 'production' ? ':remote-addr - ' : '');
const successResponseFormat = `${getIpFormat()}:method :url :status - :response-time ms`;
const errorResponseFormat = `${getIpFormat()}:method :url :status - :response-time ms - message: :message`;

const successHandler = morgan(successResponseFormat, {
  skip: (req, res) => res.statusCode >= 400,
  stream: { write: (message) => logger.info(message.trim()) },
});

const errorHandler = morgan(errorResponseFormat, {
  skip: (req, res) => res.statusCode < 400,
  stream: { write: (message) => logger.error(message.trim()) },
});

module.exports = {
  successHandler,
  errorHandler,
};

In the above-mentioned example, you can see that for configuring Winston with Morgan, you just have to set up Winston for passing the output of Morgan back to it.

Define log levels

It is necessary to define your log levels before you embark on a build with your development team. In this way, you can differentiate between log events. When you manage log events in an orderly manner then it becomes easier to get important information at a glance. There are various log levels and it is necessary that you them and their uses. Each log level provides a rough direction on the importance and urgency of a message. The common levels are mentioned below:

  • Debug: The developers use it mostly.
  • Error: The important events that will be cause the program execution to fail.
  • Info: It contains important events detailing a completed task.
  • Warn: It comprises crucial events that you should notice to prevent fails.

The developer will be able to see a detailed event and determine accordingly if it needs fixing immediately.

Use logs with a log management system

According to the size of your application, it may be helpful to pull the logs out of your application. Then, you can manage them separately with the help of a log management system. Log management systems has the ability to track and analyze logs as they happen in real-time. This in turn helps you to improve your code. In the below-mentioned example, you can see that a log management system will help you keep track of useful data. For instance, anomalies, log sources, backend errors, and production errors.

Logging in Node.js

We recommend you Loggly, McAfee Enterprise, Graylog, Sentry, Logstash, Splunk, and Logmatic for log analysis and log management tools.

Health monitoring tools

Health monitoring tools are a good way to keep track of your server performance and then identify causes of application crashes or downtime. Most health monitoring tools offer error tracking as well as alerts and also general performance monitoring. Some developers find error tracking particularly frustrating in Node.js. So, using a health monitoring tool can help alleviate some of those difficulties.

There are few below popular monitoring tools for Node.js:

  • PM2
  • Sematext
  • Appmetrics
  • ClinicJS
  • AppSignal
  • Express Status Monitor

Conclusion

In this blog, we take a look how important logging is and how it can help developers better understand their applications. We also discussed logging best practises in Node.js, including using a log library, logging HTTP requests, defining log levels, and using a log management system.

Infrastructure is completely safe or entirely error-free. Logging is a necessary step for developers who want to monitor production and cut down on errors. Logging can also be useful for other team members including QA, Support, and new programmers, as it saves valuable information to lean from and build on.