Exception Handling and Logging Errors in REST API using Javascript & Express
Tags: javascript, tutorial, webdev, api
Published: 2023-04-01 04:00:00

## Introduction
In this blog we are going to add exception handling to JavaScript REST API by coding our own **_Exception Middleware_**. We will also learn how to add **_multiple exception handlers_** to our API and _build a reusable error module_ that can be handy to when having multiple repositories in an API. Lastly, we will also see how we can add **_error logging_** capabilities to our code which logs errors to a file.

---
## Setup

In this blog I will _not_ be covering how to build a REST API in JavaScript, and I will use the exisiting GroceryAPI that I built in my other blog. It covers all the coding required to build an API from scratch in JavaScript using the **Express** framework, so do check it out:- _**[Beginner's Guide to REST API in JavaScript using Express](https://dev.to/nikkbh/beginners-guide-to-rest-api-in-javascript-using-express-jp)**_

The completed code for this tutorial can be found in the following [GitHub Repo](https://github.com/nikkbh/GroceryAPI/tree/exception-handling) in the <u>_exception-handling_</u> branch.

---
## Code
We'll start by creating a reusable error module. 

Create a file named `errorHelper.js` in the `/helpers` directory

We will write our first helper method `errorBuilder` inside of the `errorHelpers` object which we will export.
`errorBuilder` will return a custom object to client with status 500 and statusText as "Internal Server Error", the rest of the object will contain tht error message, error number and error syscall. This errorBuilder will accept an error object. We can then use this errorBuilder to build error messages for logging errors to console, logging errors to file etc.

```
let errorHelpers = {
  errorBuilder: (err) => {
    return {
      status: 500,
      statusText: "Internal Server Error",
      message: err.message,
      error: {
        errno: err.errno,
        call: err.syscall,
        code: "INTERNAL_SERVER_ERROR",
        message: err.message,
      },
    };
  },
};
```

Now, we create a `logErrorsToConsole` helper function inside errorHelpers which will use `errorBuilder` and print the error to the server console whenever it occurs.
{% gist https://gist.github.com/nikkbh/e14252d9d51834926110cd6d6a55833e.js %}

In `logErrorsToConsole` function we simple do a `console.error` of the error by passing our err object to previously created `errorBuilder` we simply add * to distinguish the error in the console and then we use the `next(err);` to move onto the next middleware available.

Now let's configure our middleware in index.js

Simply import the error helper by adding:
`let errorHelper = require("./helpers/errorHelpers");`

Then, we will add the middleware just after the router configuration.
```
// Configure router so all routes are prefixed with /api/
app.use("/api/", router);

// Configure exception logger to console
app.use(errorHelper.logErrorsToConsole);
```

Now to see our error logger middleware work we will change the spelling of the gorceries.json file in the file name variable in `groceryRepo.js` by removing the **s** from the `const FILE_NAME = "./assets/grocerie.json";`

Finally, when we hit the GET request to fetch all groceries we should see the error logged in our terminal like below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3j7vilt1chhyotsu9tbv.png)

**Adding Error Logging to a log file**
So far we setup our own middleware that logs error to console whenever an Internal Server Error occurs. 
What if we want the error logged out in a log file that stores all logs of all the errors occured for fututre refernce?

We will achieve this in three steps:
**1)** Create a logRepo.js file to handle the writes to a log file.
**2)** Add a helper method to write errors to the log file using the logRepo.
**3)** Add the helper method as a middleware to our index.js file.

Let's get started!

First step is to create a `logRepo.js` file in the `/repo` directory. The code for this will be very similar to the calls to get, update, delete and write data to our grocery store repo. 

We create a write function which takes data, req and res as the parameters.  On line 7 we create a `toWrite` variable which will store the information to be logged.

Notice that we have assigned a file to the `FILE_NAME` field on line 3, make sure to create an empty log.txt file in a logs folder.

We just append all the information that we need to see in our log file such as the _**Date and Time**_ the error occured, _**Exception Info**_  and some formatting of the log by appending * at the start and end of the message.

After that we simply use the `fs` package to write the exception message to the log file on our local file system.

{% gist https://gist.github.com/nikkbh/f27abefe9434bde18e514cf2fa876ab4  %}

Next, we configure a helper method to log errors to log file in the `errorHelpers.js` file.

We add the `logErrorsToFile` method object just after `logErrorsToConsole` method. The implementation of which is pretty straight-forward. We build the errorObject using our `errorBuilder` and assign some extra properties to it from the request object. Then we call in the `logRepo.write` and pass in this errorObject.

> NOTE: Don't forget to import the logRepo in errorHelpers.js file at the top.

```
logErrorsToFile: (err, req, res, next) => {
    let errorObject = errorHelpers.errorBuilder(err);
    errorObject.requestInfo = {
      hostName: req.hostName,
      path: req.path,
      app: req.app,
    };
    logRepo.write(
      errorObject,
      (data) => {
        console.log(data);
      },
      (err) => console.error(err)
    );
    next(err);
  }
```

Lastly, one final step is to add our middleware to handle this logging functionality in `index.js` file just after our logErrorsToConsole middleware.

```
// Configure router so all routes are prefixed with /api/
app.use("/api/", router);

// Configure exception logger to console
app.use(errorHelper.logErrorsToConsole);

// Configure exception logger to console
app.use(errorHelper.logErrorsToFile);

```

**Testing logging to text file**
Similar to how we tested our `logErrorsToConsole`, just remove the appending 's' from the file name in groceryRepo.js and send a GET request to `http://localhost:5000/api/`

You should see the error logged to console as well as the exception logged to the log.txt file as seen below with Date and Time.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sz04n8asnhiy0q1siz15.png)

If you have any doubts you can ask in the comments section below, I will be happy to help.

Happy Coding!

---
## References
https://expressjs.com/en/guide/using-middleware.html
https://expressjs.com/en/guide/error-handling.html