프로젝트에서 어떤 요청들이 오고 가는지를 확인하고, 에러가 났을때 확인하기 위해서 로그를 남기기로 했다. 명확하게 어떤 상황에 로그를 남기면 좋을지는 잘 모르겠어서, 우선은 컨트롤러로 오는 요청이 들어올 때, 그 요청이 끝날때, 그리고 에러가 발생했을시 총 3개로 나누어서 로그를 찍기로 했다.
요청에 대한것은 인터셉터를 활용하여 로그를 찍도록하였다. NestJS에서 인터셉터는 request와 response를 수행할시에 중간에서 값을 가져와서 추가적인 로직을 수행할 수 있도록 도와준다.
logging-interceptor.ts
import { CallHandler, ExecutionContext, Injectable, Logger, NestInterceptor } from '@nestjs/common';
import { catchError, from, Observable, tap } from 'rxjs';
import { EMessage } from '../response/ecustom-code.jenum';
import axios from 'axios';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger(LoggingInterceptor.name);
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const req = context.switchToHttp().getRequest();
const { method, url, body, query } = req;
const errorWebHook: string = process.env.ERR_WEB_HOOK;
this.logger.log(`[IN] ${method} ${url} ${JSON.stringify(body)} ${JSON.stringify(query)}`);
return next.handle().pipe(
tap(), // 응답이 정상적으로 끝나면 tap 안에서 수행되지만, exception 을 날리므로 error 로 처리해야함.
catchError((exception) => from(this.handleException(exception, method, url, errorWebHook))),
);
}
async handleException(exception, method, url, errorWebHook) {
if (exception.message !== EMessage.SUCCESS) {
this.logger.error(`[OUT] ${method} ${url}: ${exception.message}`);
await axios.post(errorWebHook, {
embeds: [
{
title: `[${method}] ${url}`,
description: exception.message,
color: 16711680,
},
],
});
} else {
this.logger.log(`[OUT] ${method} ${url}: ${exception.message}`);
}
throw exception;
}
}
LoggingInterceptor
intercept
next.handle()
tap
catchError
aap.module.ts
providers: [
AppService,
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
],