目的
Nest.js
に log4js
を使う方法をまとめました。
次の内容を実装します。
- 標準Loggerをlog4jsで実装 (前前回)
- ミドルウェアでリクエスト情報をログに追加 (前回)
- ログ出力時にスタック情報を追加 (今回)
ログ出力にスタック情報を追加
log4js
にはファイル名や行・列番号の出力がサポートされていますが、 CustomLogger
でラップしているため、うまく出力できません。
log4js-node で行番号の付いたログを出力したい! を参考に実装しました。
CustomLogger
にスタック情報を設定するメソッドを追加します。
logger-sample/src/logger/logger.sevice.ts
import { LoggerService, Injectable, Scope } from '@nestjs/common';
import { Logger } from 'log4js';
import { Request } from 'express';
import { basename } from 'path';
@Injectable({ scope: Scope.TRANSIENT })
export class CustomLogger implements LoggerService{
constructor(private readonly logger: Logger) {}
setRequestInfo(req: Request){
this.logger.addContext('ip',req.ip);
this.logger.addContext('method',req.method);
this.logger.addContext('uri',req.url);
}
log(message: any, context?: string) {
this.setStack(this.log);
this.logger.log(message,context? context : '');
}
error(message: any, trace?: string, context?: string) {
this.setStack(this.error);
this.logger.error(message,trace? trace : '',context? context : '');
}
warn(message: any, context?: string) {
this.setStack(this.warn);
this.logger.warn(message,context? context : '');
}
debug?(message: any, context?: string) {
this.setStack(this.debug);
this.logger.debug(message,context? context : '');
}
private setStack(caller?: Function){
const stack = this.getTrace(caller);
this.logger.addContext('file',stack.file);
this.logger.addContext('line',stack.line);
this.logger.addContext('column',stack.column);
this.logger.addContext('function',stack.func);
}
private prepareStackTrace(error, structuredStackTrace) {
const trace = structuredStackTrace[0];
return {
// method name
func: trace.getMethodName() || trace.getFunctionName() || "<anonymous>",
// file name
file: basename(trace.getFileName()),
// line number
line: trace.getLineNumber(),
// column number
column: trace.getColumnNumber()
};
}
private getTrace(caller?: Function) {
const original = Error.prepareStackTrace;
const error = {stack:{func:"",file:"",line:0,column:0}};
Error.captureStackTrace(error,caller || this.getTrace);
Error.prepareStackTrace = this.prepareStackTrace;
const stack = error.stack;
Error.prepareStackTrace = original;
return stack;
}
}
-
getTrace()
とprepareStackTrace()
でスタック情報を取得します。 - ログ出力前に出力関数自体を引数に
setStack()
を呼び出すことでログ情報にファイル名、行・列番号、関数名を出力できます。
実行結果
[2020/04/07 14.08.34.215],[INFO],[null],[null null],[logger.service.js 68:18 callFunction],RoutesResolver
[2020/04/07 14.08.34.222],[INFO],[null],[null null],[logger.service.js 68:18 callFunction],RouterExplorer
[2020/04/07 14.08.34.224],[INFO],[null],[null null],[logger.service.js 68:18 callFunction],NestApplication
[2020/04/07 14.12.07.398],[ERROR],[::1],[GET /],[app.service.js 19:21 getHello],Hello World!!
標準ライブラリの出力は相変わらずですが、リクエストの情報は正しくログ出力できています。
ただし、このスタック情報は javascript
にトランスパイル後の情報を元に出しているので参考程度になってしまします...
これで Nest.js
で log4js
を利用できるようになりました。後はプロジェクト毎にカスタマイズして利用して下さい。
今回のソースが欲しいという要望がありましたらコメント下さい。GitHubにアップします。