T-CREATOR

NestJSでアクセスログを出力するやり方を紹介

NestJSでアクセスログを出力するやり方を紹介

NestJSでアクセスログを出力する方法について解説します。アクセスログはアプリケーションの監視やデバッグに役立つため、適切に記録することが重要です。ここでは、以下の方法を紹介します。

  • ミドルウェアを利用する方法
  • カスタムロガーを作成する方法
  • Loggerクラスを活用する方法

ミドルウェアを利用する

NestJSのミドルウェアを利用すると、すべてのリクエストに対して統一的にログを記録できます。

ミドルウェアの作成

まず、リクエストごとにログを出力するミドルウェアを作成します。

tsimport { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  private readonly logger = new Logger('HTTP');

  use(req: Request, res: Response, next: NextFunction) {
    const { method, originalUrl } = req;
    const start = Date.now();

    res.on('finish', () => {
      const responseTime = Date.now() - start;
      this.logger.log(`${method} ${originalUrl} ${res.statusCode} - ${responseTime}ms`);
    });

    next();
  }
}

ミドルウェアの適用

作成したミドルウェアを適用するには、main.ts または app.module.ts に登録します。

main.ts で適用する方法

tsimport { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggerMiddleware } from './logger.middleware';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  app.use(new LoggerMiddleware().use);

  await app.listen(3000);
}
bootstrap();

app.module.ts で適用する方法

tsimport { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { LoggerMiddleware } from './logger.middleware';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('*'); // すべてのルートに適用
  }
}

これにより、すべてのリクエストとレスポンスの情報がログに記録されます。

カスタムロガーを作成する

ログの出力フォーマットを変更したい場合や、ログをファイルに保存したい場合は、カスタムロガーを作成すると便利です。

カスタムロガークラスの作成

以下のように、CustomLogger クラスを作成します。

tsimport { LoggerService, Injectable, LogLevel } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';

@Injectable()
export class CustomLogger implements LoggerService {
  private logFilePath = path.join(__dirname, '../logs/access.log');

  log(message: string) {
    this.writeLog('LOG', message);
  }

  error(message: string, trace?: string) {
    this.writeLog('ERROR', message, trace);
  }

  warn(message: string) {
    this.writeLog('WARN', message);
  }

  debug(message: string) {
    this.writeLog('DEBUG', message);
  }

  verbose(message: string) {
    this.writeLog('VERBOSE', message);
  }

  private writeLog(level: LogLevel, message: string, trace?: string) {
    const logMessage = `[${new Date().toISOString()}] [${level}] ${message} ${trace ? `\nTRACE: ${trace}` : ''}`;
    
    console.log(logMessage); // コンソールにも出力
    fs.appendFileSync(this.logFilePath, logMessage + '\n'); // ファイルに保存
  }
}

カスタムロガーの適用

作成した CustomLoggermain.ts に適用します。

tsimport { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CustomLogger } from './custom-logger.service';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { logger: new CustomLogger() });

  await app.listen(3000);
}
bootstrap();

これにより、ログをコンソールに出力しながら、ファイルにも保存できます。

Logger クラスを活用する

NestJS の組み込み Logger クラスを利用すると、簡単にログを記録できます。

Controller で Logger を使用する

tsimport { Controller, Get, Logger } from '@nestjs/common';

@Controller('example')
export class ExampleController {
  private readonly logger = new Logger(ExampleController.name);

  @Get()
  getExample() {
    this.logger.log('GET /example endpoint was called');
    return { message: 'Hello World' };
  }
}

サービス内で Logger を使用する

tsimport { Injectable, Logger } from '@nestjs/common';

@Injectable()
export class ExampleService {
  private readonly logger = new Logger(ExampleService.name);

  doSomething() {
    this.logger.debug('Doing something...');
  }
}

この方法を使うことで、特定の処理だけを記録することが可能になります。

まとめ

NestJS でアクセスログを記録するには、以下の方法があります。

方法メリット適用場面
ミドルウェアを利用すべてのリクエストを統一的に記録できる一貫したリクエストログを記録したい場合
カスタムロガーを作成出力フォーマットや保存先を自由に変更できるログを保存・カスタマイズしたい場合
Logger クラスを活用簡単にクラスごとのログを記録できる特定の処理のみログに残したい場合

運用に応じた適切な方法を選択し、ログ管理を強化しましょう。

記事Article

もっと見る