4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NestJS アクセスログ出力

Last updated at Posted at 2021-11-25

NestJS Winstonでのログ出力(アクセスログ)

NestJSプロジェクト作成

npm i -g @nestjs/cli
nest new "プロジェクト名"

Winstonインストール

yarn add winston
yarn add winston-daily-rotate-file # rotation用

カスタムLoggerのモジュール作成

nest g mo customLogger

アクセスログのservice作成

custom-logger/access-logger.service.ts
import { Injectable, LoggerService } from '@nestjs/common';
import { createLogger, format, Logger } from 'winston';
import * as DailyRotateFile from 'winston-daily-rotate-file';
import * as Transport from 'winston-transport';

@Injectable()
export class AccessLoggerService implements LoggerService {
  logger: Logger;

  constructor() {
    /** ローテーション */
    const logTransFormStream = new DailyRotateFile({
      level: 'info',
      dirname: `log/access/`,
      filename: `log_%DATE%.log`,
      datePattern: 'YYYY-MM-DD',
      zippedArchive: true,
      maxFiles: '1d',
    });

    // ログローテンションするタイミングのイベント
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    logTransFormStream.on('rotate', () => {});

    const t: Transport[] = [logTransFormStream];

    this.logger = createLogger({
      format: format.combine(format.timestamp(), format.json()),
      transports: t,
    });
  }

  log(message: string) {
    this.logger.info(message);
  }
  error(message: string) {
    this.logger.error(message);
  }
  warn(message: string) {
    this.logger.warn(message);
  }

  debug(message: string) {
    this.logger.debug(message);
  }
}

※rotateのオプション関連は下記url参照
https://github.com/winstonjs/winston-daily-rotate-file

### ログ出力の確認

custom-logger/custom-logger.module.ts
import { Module } from '@nestjs/common';
import { AccessLoggerService } from './access-logger.service';

@Module({
  providers: [AccessLoggerService],
  exports: [AccessLoggerService],
})
export class CustomLoggerModule {}
app.service.ts
import { Injectable } from '@nestjs/common';
import { AccessLoggerService } from './custom-logger/access-logger.service';

@Injectable()
export class AppService {
  constructor(private readonly accessLogger: AccessLoggerService) {}
  getHello(): string {
    this.accessLogger.log('test');
    return 'Hello World!';
  }
}
yarn start:dev

http:localhost:3000にアクセス
image.png

ログ確認

image.png

アクセス時に自動でlogを出力するように修正 ※inspectorを使用

interceptors/logging.inspector.ts
import {
  CallHandler,
  ExecutionContext,
  Injectable,
  NestInterceptor,
} from '@nestjs/common';
import { Request } from 'express';
import { catchError, Observable, throwError } from 'rxjs';
import { AccessLoggerService } from 'src/custom-logger/access-logger.service';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  constructor(private readonly accessLogger: AccessLoggerService) {}
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest<Request>();
    const requestData = {
      ip: request.ip,
      method: request.method,
      url: request.url,
      body: request.body || {},
    };

    this.accessLogger.log(JSON.stringify(requestData));

    return next.handle().pipe(
      catchError((err) => {
        // Exceptionのログを出力したい場合はここで実装
        // this.errorLogger.error({
        //   ...requestData,
        //   status: err?.status ?? err?.statusCode ?? 500,
        //   message: err?.message ?? '',
        // });
        return throwError(() => new Error(err));
      }),
    );
    // .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`)));
  }
}
app.module.ts
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomLoggerModule } from './custom-logger/custom-logger.module';
import { LoggingInterceptor } from './interceptors/logging.inspector';

@Module({
  imports: [CustomLoggerModule],
  controllers: [AppController],
  providers: [
    AppService,
    { provide: APP_INTERCEPTOR, useClass: LoggingInterceptor },
  ],
})
export class AppModule {}

テストで追加したログを削除する

app.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

再度アクセスする

image.png

ログ確認

image.png

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?