目的
Nest.js
に log4js
を使う方法をまとめました。
次の内容を実装します。
- 標準Loggerをlog4jsで実装 (今回)
- ミドルウェアでリクエスト情報をログに追加 (次回)
- ログ出力時にスタック情報を追加 (次次回)
事前準備
プロジェクトは Nest.js のCLIコマンドで生成します。
npm i -g @nestjs/cli
nest new logger-sample
以後、 標準テンプレートのプロジェクト をカスタマイズして実装していきます。
log4js
をインストール
npm i --save log4js
標準 Logger を log4js で実装
公式ドキュメントにやり方は書いてあります。 Nest.js-TECHNIQUES-Logger
LoggerServiceを実装
標準 Logger
を書き換えるために LoggerService
を実装します。
logger-sample/src/logger/logger.service.ts
import { LoggerService, Injectable, Scope } from '@nestjs/common';
import { Logger } from 'log4js';
@Injectable({ scope: Scope.TRANSIENT })
export class CustomLogger implements LoggerService{
constructor(private readonly logger: Logger) {}
log(message: any, context?: string) {
this.logger.log(message,context? context : '');
}
error(message: any, trace?: string, context?: string) {
this.logger.error(message,trace? trace : '',context? context : '');
}
warn(message: any, context?: string) {
this.logger.warn(message,context? context : '');
}
debug?(message: any, context?: string) {
this.logger.debug(message,context? context : '');
}
}
- リクエスト毎に出力情報は変わるため、スコープは
TRANSIENT
にしています。 -
log4js
のLogger
はコンストラクタから渡すようにしました。 -
verbose()
は使わないため実装していません。
LoggerModule を実装
CustomLogger
を公開するために LoggerModule
を実装します。
logger-sample/logger/logger.module.ts
import { Module } from "@nestjs/common";
import { CustomLogger } from './logger.service';
import {configure,getLogger} from 'log4js';
const config = {
"appenders":{
"access":{
"type": "file",
"filename": "log/trace.log",
"maxLogSize": 10485760,
"category": "access",
"layout": {
"type": "pattern",
"pattern": "[%d{yyyy/MM/dd hh.mm.ss.SSS}],[%p],[%X{ip}],[%X{method} %X{uri}],[%X{file} %X{line}:%X{column} %X{function}],%m"
}
},
"console":{
"type": "stdout",
"layout": {
"type": "pattern",
"pattern": "[%d{yyyy/MM/dd hh.mm.ss.SSS}],[%p],[%X{ip}],[%X{method} %X{uri}],[%X{file} %X{line}:%X{column} %X{function}],%m"
}
}
},
"categories": {
"default":{
"appenders": ["access","console"],
"level": "INFO"
}
}
}
const loggerFactory = {
provide:CustomLogger,
useFactory:()=>{
configure(config);
return new CustomLogger(getLogger("default"));
}
}
@Module({
providers:[loggerFactory],
exports:[loggerFactory]
})
export class LoggerModule {}
-
config
はlog4js
の設定情報です。次の設定をしています。- ファイル(logger-sample/log/trace.log)と標準出力にログを出力する。
- リクエスト、スタック情報を追加したログフォーマットに変更
-
loggerFactory
はカスタムインスタンスを作成する方法です。 詳しくは 公式 を参照してください。
LoggerModule を AppModule にインポートする。
imports
に LoggerModule
を追加するだけです。
logger-sample/src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { LoggerModule } from './logger/logger.module';
@Module({
imports: [LoggerModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Nest の標準 Logger を無効化して log4js を設定
main.ts
を変更して、標準 Logger
の無効化と CustomLogger
を設定します。
logger-sample/src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CustomLogger } from './logger/logger.service';
async function bootstrap() {
const app = await NestFactory.create(AppModule,{logger:false});
app.useLogger(app.get(CustomLogger));
await app.listen(3000);
}
bootstrap();
app.service.ts
で実際に log4js
でログ出力を記述します。
logger-sample/src/app.service.ts
import { Injectable } from '@nestjs/common';
import { CustomLogger } from './logger/logger.service';
@Injectable()
export class AppService {
constructor(private logger: CustomLogger){}
getHello(): string {
this.logger.error('Hello World!!');
return 'Hello World!';
}
}
-
constructor
でCustomLogger
を注入します。 -
getHello()
のthis.logger.error('Hello World!!');
でログ出力しています。
実際に動かした結果
13:28:05 - Found 0 errors. Watching for file changes.
[2020/04/07 13.28.06.101],[INFO],[null],[null null],[null null:null null],RoutesResolver
[2020/04/07 13.28.06.106],[INFO],[null],[null null],[null null:null null],RouterExplorer
[2020/04/07 13.28.06.108],[INFO],[null],[null null],[null null:null null],NestApplication
[2020/04/07 13.28.09.370],[ERROR],[null],[null null],[null null:null null],Hello World!!
null
が多いですが、後の実装で設定しておくのでひとまずOK
これで標準 Logger
を log4js
に置き換えることができました。