Exception Handling in Node.js Applications using log4js

yogitakadam14

YogitaKadam14

Posted on June 2, 2023

Exception Handling in Node.js Applications using log4js

Exception handling plays a crucial role in ensuring the stability and reliability of Node.js applications. By effectively handling exceptions, developers can identify and address errors, improve debugging, and provide a smoother user experience. In this blog post, we will explore how to handle exceptions in a Node.js application using the popular logging library, log4js with customized configurations.

When logging messages, it is important to easily identify the log level, such as whether it is an error, warning, or information.

To use the Log4Js package, follow these basic steps:

1.Install the package by running the following command:

npm install log4js
Enter fullscreen mode Exit fullscreen mode

You can find more information about the Log4js package on the npmjs.com website.

2.Create a new file called logger.ts and add the following code:

// Description: This file contains the logger configuration and custom logger functions
import { getLogger, configure } from 'log4js';
//configure logger
//type of appenders: console, file, dateFile, logLevelFilter, multiFile, stdout, stderr, cluster, log4js
//level of appenders: all, trace, debug, info, warn, error, fatal, mark, off
configure(
    {
        appenders: {          
            console: { type: "console" }
        },
        categories: {
            default: {
                appenders: ["console"],
                level: 'all'

            }
        }
    }
);
//get logger
const logger = getLogger();
//custom error logger
const errorLogger = (error: Error, functionName:string)=>{

    let responseErrorMessage = error.message;
    logger.error(`Function Name: ${functionName} \n Message: ${responseErrorMessage} \n Stack: ${error.stack}`)

}
//custom info logger
const infoLogger = (infoMessage: string, functionName:string)=>{

    logger.info(`Function Name: ${functionName} Message: ${infoMessage}`);

}
//custom warning logger
const warnLogger = (warnMessage: string, functionName:string)=>{

    logger.warn(`Function Name: ${functionName} Warning: ${warnMessage}`);    

}
export default {errorLogger,infoLogger,warnLogger}
Enter fullscreen mode Exit fullscreen mode

This code sets up a logger configuration and defines three custom logger functions: errorLogger, infoLogger, and warnLogger. Here's a breakdown of the code:

• The code imports the getLogger and configure functions from the 'log4js' library.
• The configure function is called to set up the logger configuration. In this configuration, a single appender of type "console" is defined
• The logger configuration specifies that all log events should be appended to the console appender.
• The getLogger function is called to retrieve a logger instance
• The errorLogger function takes an Error object and a functionName string as parameters. It logs an error message, including the function name, error message, and stack trace.
• The infoLogger function takes an infoMessage string and a functionName string as parameters. It logs an info message, including the function name and info message.
• The warnLogger function takes a warnMessage string and a functionName string as parameters. It logs a warning message, including the function name and warning message
• Finally, the code exports an object containing the three custom logger functions: errorLogger, infoLogger, and warnLogger.

Overall, this code sets up a logging configuration using the log4js library and provides custom logger functions for logging errors, info messages, and warnings with additional context information like function names.

3.Use the logger in your function. Here is an example using logger.ts:

It logs various messages at different stages of execution using a custom logger object.

import { Request, Response } from "express";
import models from "../models"
import logger from "../log/logger";
const getContact = async (req: Request, res: Response) => {

    logger.infoLogger("Start", "getContact");

    let contactDetails: {count:number,
          rows:{
                 Id:string,  
                 LastName:string, 
                 MiddleName:string, 
                 FirstName:string, 
                 ContactNumber:string, 
                 Email:string}[]};
    try {
        const contactnumber=req.params.contactnumber
        contactDetails = await models.Contact.findAndCountAll({

            offset: 0,
            //limit: max,    
            attributes: [
            "Id",           
            "LastName",
            "MiddleName",
            "FirstName",            
            "ContactNumber",
            "Email"
            ],
            where: { IsActive: 1,ContactNumber:contactnumber }
        });
        if (contactDetails.count == 0) {
            logger.infoLogger("No data found", "getContact");
            logger.warnLogger( `No data found for contact number: ${contactnumber}`, "getContact");
            return res.status(204).json({ message: 'No data found' });
        }
        else
            return res.status(200).json({ data: contactDetails });
    }catch (error: any) {

        logger.errorLogger(error, "getContact");

        if (error.statusCode) {
            return res.status(error.statusCode).json({ message: error.message });
        } else {
            return res.status(500).json({message: `An unexpected error occurred. ${error.message}` });
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

4.Below is the expected output in various scenarios:

• When the data not found:
Logging level: Info
Color: Green
Output:
Image description
• When an unexpected error occurs (catch block):
Logging level: Error
Color: Red
Output:
Image description
• When a warning message is logged:
Logging level: Warning
Color: Yellow
Output:
Image description
To review logs on Azure, you can refer to the article Exception Handling, Logging, and Notifications in Azure App Services: A Comprehensive Guide for detailed instructions.

By following best practices and leveraging the power of log4js, developers can enhance their Node.js applications' overall quality and maintainability. Furthermore, the comprehensive guide on exception handling, logging, and notifications in Azure App Services provides valuable insights for managing logs in Azure environments. With these practices in place, developers can build robust and resilient Node.js applications that meet the highest standards of stability and reliability.

💖 💪 🙅 🚩
yogitakadam14
YogitaKadam14

Posted on June 2, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related