1
1

More than 3 years have passed since last update.

Nest.js + log4js ~ログ出力にスタック情報追加~

Last updated at Posted at 2020-04-07

目的

Nest.jslog4js を使う方法をまとめました。
次の内容を実装します。

ログ出力にスタック情報を追加

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.jslog4js を利用できるようになりました。後はプロジェクト毎にカスタマイズして利用して下さい。

今回のソースが欲しいという要望がありましたらコメント下さい。GitHubにアップします。

1
1
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
1
1