Implementing Nest JS Default Logger in your Application

Amir Mustafa
5 min readFeb 24, 2024

→ In today’s article we will learn and implement the Nest JS default logger that comes with it.

Why Do We Need a Logger?

→ Logging is helpful in various operations — debugging production bug, some info

→ There will be times when your application does not behave as it should have been — good for tracking some useful operation for Ops team, and many more

→ For understanding the issue, will be a saviour.

Some Things to Know:

→ Logger must be used at the time of project development.

→ We will be using the default logger of nest js i.e. Logger from @nestjs/common

→ We do not log any sensitive information.

Types of Logs:

→ There are 5 types of logs: Log, Warning, Error, Debug, Verbose

  1. Log — General purpose information for logging purpose
  2. Warning — Unhandled Issue that is not fatal or destructive
  3. Error — Unhandled Issue that is fatal or destructive
  4. Debug — Useful information that can help us debug the logic in case or error or warning (Intended for Developers)
  5. Verbose — Information providing insights of the behavior of the app (Intended for Ops) — having too much information

Implementing in Nest JS:

STEP 1: Logger comes with Nest JS Application. We have to import it.

Path: /src/main.ts (entry file Nest JS)

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
import { TransformInterceptor } from './transform.interceptor';
import { Logger } from '@nestjs/common'; // IMPORTING LOGGER

async function bootstrap() {
const logger = new Logger(); // CREATING INSTANCE OF LOGGER
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
app.useGlobalInterceptors(new TransformInterceptor());
const port = 3000;
await app.listen(port);

logger.log(`Application running on port ${port}`); // LOGGER OF TYPE LOG
}
bootstrap();

→ We have built a CRUD operation of tasks where user can create, read, update or delete tasks

Eg 2: API: Get Task API with filters applied:

i.e. localhost:3000/tasks/status=OPEN

Description: In the Task controller, will add some logs. We will log — username and filters applied at fetching get Tasks

import {
Body,
Controller,
Get,
Param,
Post,
Delete,
Patch,
Query,
UseGuards,
Logger, // LOGGER IMPORTED
} from '@nestjs/common';


import { User } from 'src/auth/user.entity';

@Controller('tasks')
@UseGuards(AuthGuard())
export class TasksController {
private logger = new Logger('TasksController'); // LOGGER INITIALIZING WITH CONTEXT
constructor(private taskService: TasksService) {}

@Get()
getTasks(@Query() filterDto: GetTasksFilterDto, @GetUser() user: User): Promise<Task[]> {
// LOGGER OF TYPE VERBOSE PRINTED
this.logger.verbose(`User "${user.username}" retrieving all tasks, Filters: ${JSON.stringify(filterDto)}`);
return this.taskService.getTasks(filterDto, user);

→ We see verbose type information printed in the Nest JS terminal.

Eg 3: Applying Logger in Get Tasks API (without filters applied)

i.e. localhost:3000/tasks

Eg 4: Applying logger in Create Tasks API:

→ Here we will log the user who is creating the task and the data

@Post()
createTask(
@Body() createTaskDto: CreateTaskDto,
@GetUser() user: User
): Promise<Task> {
// LOGGING USER INFO, WHO IS CREATING TASK AND DATA
this.logger.verbose(`User ${user.username} creating a new task. Data: ${JSON.stringify(createTaskDto)}`);
return this.taskService.createTask(createTaskDto, user);
}

Eg 5: Applying Logger of type error in Get Tasks DB operation

→ Here we are using try..catch block

→ We will be using a logger in the catch block

Path: src/tasks/tasks.service.ts

import { Injectable, InternalServerErrorException, Logger, NotFoundException } from '@nestjs/common';
import { TaskStatus } from './task-status.enum';
import { GetTasksFilterDto } from './dto/get-tasks.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Task } from './task.entity';
import { CreateTaskDto } from './dto/create-task.dto';
import { Repository } from 'typeorm';
import { User } from 'src/auth/user.entity';

@Injectable()
export class TasksService {
private logger = new Logger('TasksService'); // LOGGER INSTANTIATED

constructor(
@InjectRepository(Task)
private taskRepository: Repository<Task>,
) {}

async getTasks(filterDto: GetTasksFilterDto, user: User): Promise<Task[]> {
const query = this.taskRepository.createQueryBuilder('task');
const { status, search } = filterDto;

query.where({ user: user.id});

if (status) {
query.andWhere('task.status = :status', { status });
}

if (search) {
query.andWhere(
'(LOWER(task.title) LIKE LOWER(:search) OR LOWER(task.description) LIKE LOWER(:search))',
{ search: `%${search}%` },
);
}

try {
const tasks = await query.getMany();
return tasks;
} catch (error) {
// LOGGING ERROR
this.logger.error(`Failed to get tasks for user ${user.username}, Filters: ${JSON.stringify(filterDto)}`, error.stack);
throw new InternalServerErrorException();
}


}
}

→ Let us forcefully create error.

if (status) {
query.andWhere('task.statusGKHGADSKAAG = :status', { status }); // WRONG COLUMN IN DB
}

→ In Postman, we got the error — Internal Server Error.

→ Let us check our Nest JS terminal

Conclusion:

Many loggers are used globally in projects. They are very useful in debugging and understanding it.

We were using Azure Cosmos DB in our project. Suddenly queries were not working. CPU utilization was 100% (called RU). Charges are based on the number of times the database query hits.

As the RU’s was 100% fetching data was failing. These logs saved our day and we got the error message which we fixed by vertical scaling infra-level changes. Ideally in every project, we should use loggers.

Thank you for reading till the end 🙌 . If you enjoyed this article or learned something new, support me by clicking the share button below to reach more people and/or subscribe Happy Learnings !! to see some other tips, articles, and things I learn about and share there.!

--

--

Amir Mustafa

JavaScript Specialist | Consultant | YouTuber 🎬. | AWS ☁️ | Docker 🐳 | Digital Nomad | Human. Connect with me on https://www.linkedin.com/in/amirmustafa1/