Nest(TypeScript)で遊んでみる 〜Logging編〜
Posted on September 09, 2018 at 22:00 (JST)
今回はNestにて log4js-node を使用する方法について記載する。
Nestの公式ドキュメントに記載されている中から、DIを利用する方法を選択し実装した。
流れは下記の通り。
- ライブラリを追加
- Loggerを作成
- DIするためのモジュール作成
- フレームワーク本体のログ出力処理に使用するための設定変更
- ローカル開発時は
debug
レベル以上のログを出力するよう設定
作成したコード [ nest-angular-sample: works/02_logging ]
動作環境
OS: macOS High Sierra ver. 10.13.4
Nodejs: v8.10.0
npm: 5.6.0
nest: 5.4.0
1. ライブラリを追加
下記コマンドで log4js
をインストールする
$ npm install --save log4js
2. Loggerを作成
log4js
を利用してログ出力を行うためのServiceを用意する。
フレームワーク本体のログ出力処理を統合するため、@nestjs/common/LoggerService
を implements する。
log4jsの設定については log4js-nodeの公式ドキュメント を参照。
今回のサンプルは出力対象となる全てのログは標準出力、かつエラーログのみファイル出力を行なっている。
出力可能とするエラーレベルは環境変数で指定し、未指定の場合は info
以上のもののみ出力するようにしている。
[src/logger/logger.service.ts]
import { LoggerService } from '@nestjs/common';
import { configure, getLogger } from 'log4js';
const defaultLogger = getLogger();
const defaultLoggerLevel = process.env.LOGGER_LEVEL || 'info';
const layout = {
type: 'pattern',
pattern: '%d{ISO8601_WITH_TZ_OFFSET} [%p] %m',
};
configure({
appenders: {
stdout: { type: 'stdout', layout },
file: {
type: 'file',
filename: 'application.error.log',
layout
},
},
categories: {
default: { appenders: ['stdout'], level: defaultLoggerLevel },
error: { appenders: ['stdout', 'file'], level: 'error' },
},
});
export class Logger implements LoggerService {
log(message: string) {
this.info(message);
}
debug(message: string) {
defaultLogger.debug(message);
}
info(message: string) {
defaultLogger.info(message);
}
warn(message: string) {
defaultLogger.warn(message);
}
error(message: string, trace?: string) {
const errorLogger = getLogger('error');
if (trace) {
errorLogger.error(`${message}\n${trace}`);
} else {
errorLogger.error(message);
}
}
}
※ ログファイル出力ではファイルローテーションを考慮する必要があるが、サンプルなので割愛。
3. DIするためのモジュール作成
作成した Logger
を読み込む Module
を作成する。
[src/logger/logger.module.ts]
import { Module } from '@nestjs/common';
import { Logger } from './logger.service';
@Module({
providers: [Logger],
exports: [Logger],
})
export class LoggerModule {};
作成した LoggerModule
を AppModule
の imports
に指定する。
[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 {}
4. フレームワーク本体のログ出力処理に使用するための設定変更
下記ソースでは app.get(Logger)
にてDIコンテナからLoggerインスタンスを取得している。
DIでLoggerを使用する場合でも、モジュール初期化時のログにだけは適用できない点に注意が必要。
モジュール初期化時(DIコンテナにLoggerインスタンスを格納する処理を含む)のログはNestのデフォルトLoggerを使用して出力される。
上記ログのみフォーマット等が揃わないのが気になる場合、アプリケーション初期化処理メソッドのオプションとして logger: false
を指定するとモジュール初期化時のログが出力されなくなる。
[src/main.ts]
const app = await NestFactory.create(AppModule, {
logger: false,
});
app.useLogger(app.get(Logger));
※ src/main.hmr.ts
も同様の設定を行う。
5. ローカル開発時は debug レベル以上のログを出力するよう設定
$ npm run start:hmr
実行時に環境変数へ LOGGER_LEVEL=debug
を追加する。
[package.json]
"start:hmr": "LOGGER_LEVEL=debug node dist/server",
以上。