Dan
Dan

Reputation: 69

I need suggestion in saving logs in NestJS

I need suggestion about how to properly or most efficient way to save user logs in database.

So I want to log every time the user do CRUD. I want to save the

what I have, in user service layer I call another service name auditService which insert the logs in database.

async create(createUserDto: CreateUserDto): Promise<User> {
try {
  const user = new User();
  user.email = createUserDto.email;
  user.role = createUserDto.role;
  user.firstName = createUserDto.firstName;
  user.lastName = createUserDto.lastName;

  const rs = await this.usersRepository.save(user);

  const audit = new AuditLog();
  audit.userId = rs.id;
  audit.eventType = CREATE_CUSTOMER_SUCESS;
  audit.rqMessage = createUserDto;
  audit.rsMessage = rs;

  //Audit Service which save the logs.
  await this.auditService.create(audit); 

  return rs;
} catch (err) {
  // Error
} 

Well, this works. but I know there is more efficient way than this. Thank you.

Upvotes: 1

Views: 3991

Answers (1)

Jackson Silva
Jackson Silva

Reputation: 162

To have full access over request and Response, the best way is by setting a Logger Interceptor or Middleware.

For example, if you are keeping the log to MongoDB, here is an example:

    @Injectable()
export class LoggingInterceptor implements NestInterceptor {
    constructor(@InjectModel('Log') private logModel: Model<LogDocument>) {}

    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        const req = context?.switchToHttp()?.getRequest<Request>();
        const { statusCode } = context?.switchToHttp()?.getResponse<Response>();
        const { originalUrl, method, params, query, body, headers, user } = req;
        const requestTime = new Date();

        const request: RequestInterface = {
            originalUrl,
            method,
            params,
            query,
            body,
            headers,
        };

        return next.handle().pipe(
            tap((data) => {
                const response = { statusCode, data };
                this.insertMongo(originalUrl, request, response, requestTime);
            }),
        );
    }

    private async insertMongo(
        endpoint: string,
        request: RequestInterface,
        response: ResponseInterface,
        requestTime: Date,
    ): Promise<LogDocument> {
        const logInfo: CreateLogDto = {
            endpoint,
            request,
            response,
            requestTime,
        };
        const createdLog = new this.logModel(logInfo);
        return createdLog.save();
    }
}

It will handle the Request, Response, Context, and Timestamp of every request intercepted.

To use it in a module, you just have to add an APP_INTERCEPTOR provider to it. In the case of the example logger, it should look like this:

providers: [
        { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
    ],

Upvotes: 1

Related Questions