経緯
NestJSをバックエンドAPIとして利用しているのですが、
あるフロントの1ページにアクセスした際にたくさんのデータ取得用apiが叩かれるため、各APIのコントローラーで
「SQLログを出しているけど、どのAPI内で実行されているか」
「各APIでどれくらいの時間がかかっているのか」
が少しわかりづらいなあと感じつつ、それぞれログを仕込んでいました。
調べてみると、NestJSにはinterceptorという機能があり、それを使えば全てのコントローラーの最初、最後に統一した処理を追加できるので、公式にある処理ほぼそのままですが試してみました。
※Laravelのミドルウェアのようなイメージです。
手順
logging.interceptor.ts
というファイルを作成します。
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// リクエストオブジェクトを取得
const request = context.switchToHttp().getRequest();
// コントローラーのメタデータを取得
const handler = context.getHandler();
const controller = context.getClass().name;
const { method, url } = request;
const now = Date.now();
console.log(`--- コントローラー呼び出し開始 ---`);
console.log(`Controller: ${controller}`);
console.log(`Method: ${method}`);
console.log(`URL: ${url}`);
console.log(`Timestamp: ${new Date().toISOString()}`);
return next.handle().pipe(
tap(() => {
const duration = Date.now() - now;
console.log(`--- コントローラー呼び出し終了 ---`);
console.log(`Duration: ${duration}ms`);
}),
);
}
}
main.ts
でuseGlobalInterceptors
として読み込みます。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingInterceptor } from './logging.interceptor';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new LoggingInterceptor()); //ここ
await app.listen(3000);
}
bootstrap();