API with NestJS #86. Logging with the built-in logger when using raw SQL

JavaScript NestJS SQL

This entry is part 86 of 168 in the API with NestJS

Troubleshooting a deployed application can be challenging. We can’t use the debugger and stop an application used by other people. Instead, we need to implement logs that we can inspect if we suspect that our API is not working as expected. In this article, we look at the logger built into NestJS and use it in different cases.

Logger available in NestJS

NestJS is equipped with a logger ready to use out of the box. The official documentation suggests creating an instance of the logger on top of each class we want to use it in.

users.service.ts

Log levels

A crucial concept we need to learn is the level of the log. There are a few to choose from, sorted by severity:

  1. error
  2. warn
  3. log
  4. verbose
  5. debug

Each logger instance has a set of methods that correspond with the above levels.

users.service.ts

The more severe a particular log, the more alarmed we should be. For example, a user trying to sign up using an occupied email address is not a reason to panic. Because of that, above, we use the function.

We can specify what levels of logs we want to appear in our terminal. To do that, we need to adjust our function.

main.ts

It is a common approach to disregard some of the logs in the production environment. We might want to avoid having too many logs in production so that we see a potential issue more clearly.

main.ts

A surprising thing might be that providing turns on all of the log levels. When we look at the isLogLevelEnabled function we can see that NestJS looks for the highest severity included in the array and turns on all of the logs with the lower severity too. Above, we provide a full array for the sake of readability.

Once we do the above, logs start appearing in our terminal. There we can see that thanks to providing the name of the service with , the name appears at the beginning of the log.

Using the logger in an interceptor

The above approach can be handy when handling some specific cases. Unfortunately, covering all possible situations with logs would be pretty demanding. Fortunately, we can use the power of interceptors that NestJS offers us. Let’s write an interceptor that allows us to cover a particular endpoint with a wide variety of logs.

authentication.controller.ts

The job of the is to gather information bout the request and response. We can write an interceptor that binds some logic before the method execution.

If you want to know more about interceptors, check out API with NestJS #5. Serializing the response with interceptors

logger.interceptor.ts

Above a few important things happen:

  1. we get the and object associated with a particular request,
  2. we wait for the finish event emitted by NodeJS
  3. we use the appropriate log level based on the status code.

If we want our interceptor to apply to every method in a given controller, we can apply it to the whole class.

authentication.controller.ts

If we would like to apply the above logic to all of our controllers, we can use our interceptor globally with the method.

main.ts

Logging SQL queries

A helpful thing to do might be to log all SQL queries in our application. Unfortunately, the node-postgres library does not offer any logging functionalities.

Thankfully, it’s pretty easy to inject logging functionalities into our when performing simple queries.

database.service.ts

The problem arises when we perform transactions and implement the function.

If you want to know more about transactions check out API with NestJS #76. Working with transactions using raw SQL queries

database.service.ts

Once we return the client, we no longer control how it executes queries. Fortunately, we can deal with the above problem using a proxy.

If you want to know more about proxies, check out Understanding JavaScript Proxy. Preserving backward compatibility in a library

database.service.ts

Thanks to the above approach, as soon as some other service gets a pool client and runs a query, it runs through our proxy first and logs the appropriate message.

Summary

In this article, we’ve learned how to work with the logger built into NestJS. We’ve covered a variety of cases in which we might need logging. It included logging messages automatically for specific endpoints and SQL queries. A thorough approach to logging can help us when there is a problem in our application, so it is worth spending some time on.

Series Navigation<< API with NestJS #85. Defining constraints with raw SQLAPI with NestJS #87. Writing unit tests in a project with raw SQL >>
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments