序章

効果的なロギングソリューションは、あらゆるアプリケーションの成功に不可欠です。 このガイドでは、 Winston と呼ばれるロギングパッケージに焦点を当てます。これは、非常に用途の広いロギングライブラリであり、NPMダウンロード統計に基づいてNode.jsアプリケーションで利用できる最も人気のあるロギングソリューションです。 Winstonの機能には、複数のストレージオプションとログレベル、ログクエリ、さらには組み込みのプロファイラーのサポートが含まれます。 このチュートリアルでは、Winstonを使用して、このプロセスの一部として作成するNode / Expressアプリケーションをログに記録する方法を示します。 また、Winstonを Morgan と呼ばれるNode.js用の別の人気のあるHTTPリクエストミドルウェアロガーと組み合わせて、HTTPリクエストデータログを他の情報と統合する方法についても見ていきます。

このチュートリアルを完了すると、Ubuntuサーバーで小さなNode/Expressアプリケーションを実行できるようになります。 また、Winstonを実装して、エラーとメッセージをファイルとコンソールに記録します。

前提条件

このガイドを開始する前に、次のものが必要です。

これらの前提条件が整ったら、アプリケーションをビルドしてWinstonをインストールできます。

ステップ1—基本的なNode/Expressアプリを作成する

Winstonの一般的な用途は、Node.jsで構築されたWebアプリケーションからのイベントをログに記録することです。 Winstonを組み込む方法を完全に示すために、Expressフレームワークを使用して単純なNode.jsWebアプリケーションを作成します。 基本的なWebアプリケーションを実行するために、Node /ExpressWebアプリケーションをすばやく実行するためのコマンドラインツールであるexpress-generatorを使用します。 前提条件の一部としてNodePackage Manager をインストールしたため、 npm インストールするコマンド express-generator. また、 -g フラグ。パッケージをグローバルにインストールして、既存のノードプロジェクト/モジュールの外部でコマンドラインツールとして使用できるようにします。 次のコマンドを使用してパッケージをインストールします。

  1. sudo npm install express-generator -g

express-generator インストールすると、を使用してアプリを作成できます express コマンドの後に、プロジェクトに使用するディレクトリの名前が続きます。 これにより、開始するために必要なすべてのものを備えたアプリケーションが作成されます。

  1. express myApp

次に、 Nodemon をインストールします。これにより、変更を加えるたびにアプリケーションが自動的に再ロードされます。 これらの変更を有効にするには、ソースコードに変更が加えられたときにNode.jsアプリケーションを再起動する必要があります。 Nodemonは自動的に変更を監視し、アプリケーションを再起動します。 そして、私たちが使用できるようにしたいので nodemon コマンドラインツールとして、 -g 国旗:

  1. sudo npm install nodemon -g

アプリケーションのセットアップを完了するには、アプリケーションディレクトリに移動し、次のように依存関係をインストールします。

  1. cd myApp
  2. npm install

デフォルトでは、で作成されたアプリケーション express-generator ポート3000で実行するため、ポートがファイアウォールによってブロックされていないことを確認する必要があります。 ポート3000を開くには、次のコマンドを実行します。

  1. sudo ufw allow 3000

これで、Webアプリケーションを起動するために必要なものがすべて揃いました。 これを行うには、次のコマンドを実行します。

  1. nodemon bin/www

これにより、ポート3000で実行されているアプリケーションが起動します。 次のURLにアクセスして、機能していることをテストできます。 http://your_server_ip:3000 Webブラウザで。 次のように表示されます。

この時点で、サーバーへの2番目のSSHセッションを開始して、このチュートリアルの残りの部分で使用し、元のセッションで実行を開始したばかりのWebアプリケーションを残しておくことをお勧めします。 この記事の残りの部分では、これまで使用していて、現在アプリケーションを実行しているSSHセッションをセッションAと呼びます。 コマンドの実行とファイルの編集に新しいSSHセッションを使用し、このセッションをセッションBと呼びます。 特に明記されていない限り、残りのすべてのコマンドはセッションBで実行する必要があります。

ステップ2-Node.jsアプリケーションのカスタマイズ

によって作成されたデフォルトのアプリケーション express-generator 始めるのに素晴らしい仕事をしてくれます。それには、すべてのHTTPリクエストに関するデータをログに記録するために使用するMorganHTTPロギングミドルウェアも含まれています。 また、Morganは出力ストリームをサポートしているため、Winstonに組み込まれているストリームサポートとの優れたペアリングを実現し、HTTPリクエストデータログをWinstonでログに記録するために選択した他のログと統合できるようにします。

デフォルトでは、 express-generator ボイラープレートは、変数loggerを参照するときに使用します morgan パッケージ。 使用するので morganwinston、どちらもロギングパッケージであるため、どちらか一方をloggerと呼ぶと混乱する可能性があります。 それでは、編集して変更しましょう app.js プロジェクトのルートにあるファイルといくつかの変更を行います。

開く app.js 編集には、 nano 指図:

  1. nano ~/myApp/app.js

ファイルの先頭近くにある次の行を見つけます。

〜/ myApp / app.js
...
var logger = require('morgan');
...

次のように変更します。

〜/ myApp / app.js
...
var morgan = require('morgan');
...

また、変数 logger がファイル内で参照されている場所を見つけて、次のように変更する必要があります。 morgan. その間に、で使用されるログ形式を変更しましょう。 morgan パッケージに combined、これは標準のApacheログ形式であり、リモートIPアドレスやユーザーエージェントHTTPリクエストヘッダーなどの有用な情報がログに含まれます。

これを行うには、次の行を見つけます。

〜/ myApp / app.js
...
app.use(logger('dev'));
...

次のように変更します。

〜/ myApp / app.js
...
app.use(morgan('combined'));
...

これらの変更は、Winston構成を統合した後、いつでも参照しているロギングパッケージをよりよく理解するのに役立ちます。

終了し、次のように入力してファイルを保存します CTRL-X、 それから Y、 その後 ENTER.

アプリがセットアップされたので、Winstonでの作業を開始する準備が整いました。

ステップ3—Winstonのインストールと構成

これで、Winstonをインストールして構成する準備が整いました。 このステップでは、の一部として利用できるいくつかの構成オプションについて説明します。 winston ファイルとコンソールに情報を記録するロガーをパッケージ化して作成します。

インストールするには winston 次のコマンドを実行します。

  1. cd ~/myApp
  2. npm install winston

アプリケーションのサポートまたはユーティリティ構成ファイルを特別なディレクトリに保存しておくと便利なことが多いので、作成してみましょう。 config を含むフォルダ winston 構成:

  1. mkdir ~/myApp/config

それでは、次のファイルを含むファイルを作成しましょう。 winston 構成、これを呼び出します winston.js:

  1. touch ~/myApp/config/winston.js

次に、ログファイルを含むフォルダーを作成します。

  1. mkdir ~/myApp/logs

最後に、インストールしましょう app-root-path、Node.jsでパスを指定するときに役立つパッケージ。 このパッケージはWinstonに直接関連していませんが、Node.jsコードでファイルへのパスを指定するときに非常に役立ちます。 これを使用して、プロジェクトのルートからWinstonログファイルの場所を指定し、醜い相対パス構文を回避します。

  1. npm install app-root-path --save

ロギングの処理方法を構成するために必要なものはすべて整っているので、構成設定の定義に進むことができます。 開くことから始めます ~/myApp/config/winston.js 編集用:

  1. nano ~/myApp/config/winston.js

次に、 app-root-pathwinston パッケージ:

〜/ myApp / config / winston.js
var appRoot = require('app-root-path');
var winston = require('winston');

これらの変数を設定すると、トランスポートの構成設定を定義できます。 トランスポートは、ログに使用されるストレージ/出力メカニズムを参照するWinstonによって導入された概念です。 Winstonには、 console file 、およびHTTPの3つのコアトランスポートが付属しています。 このチュートリアルでは、コンソールトランスポートとファイルトランスポートに焦点を当てます。コンソールトランスポートは情報をコンソールに記録し、ファイルトランスポートは情報を指定されたファイルに記録します。 各トランスポート定義には、ファイルサイズ、ログレベル、ログ形式などの独自の構成設定を含めることができます。 各トランスポートに使用する設定の概要は次のとおりです。

  • level-ログに記録するメッセージのレベル。
  • filename-ログデータの書き込みに使用するファイル。
  • handleExceptions-未処理の例外をキャッチしてログに記録します。
  • json-ログデータをJSON形式で記録します。
  • maxsize -新しいファイルが作成される前のログファイルの最大サイズ(バイト単位)。
  • maxFiles-ログファイルのサイズを超えたときに作成されるファイルの数を制限します。
  • colorize-出力を色付けします。 これは、コンソールログを確認するときに役立ちます。

ログレベルはメッセージの優先度を示し、整数で示されます。 ウィンストンは npm 0から5(最高から最低)に優先順位が付けられたログレベル:

  • 0 :エラー
  • 1 :警告
  • 2 :情報
  • 3 :冗長
  • 4 :デバッグ
  • 5 :ばかげている

特定のトランスポートのログレベルを指定すると、そのレベル以上のすべてがログに記録されます。 たとえば、のレベルを指定することによって info、レベルで何でも error, warn、 また info ログに記録されます。 ロガーを呼び出すときにログレベルが指定されます。つまり、エラーを記録するために次の操作を実行できます。 logger.error('test error message').

の構成設定を定義できます fileconsole で輸送 winston 次のような構成:

〜/ myApp / config / winston.js
...
var options = {
  file: {
    level: 'info',
    filename: `${appRoot}/logs/app.log`,
    handleExceptions: true,
    json: true,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
    colorize: false,
  },
  console: {
    level: 'debug',
    handleExceptions: true,
    json: false,
    colorize: true,
  },
};

次に、新しいインスタンスを作成します winston で定義されたプロパティを使用したファイルおよびコンソールトランスポートを備えたロガー options 変数:

〜/ myApp / config / winston.js
...
var logger = new winston.Logger({
  transports: [
    new winston.transports.File(options.file),
    new winston.transports.Console(options.console)
  ],
  exitOnError: false, // do not exit on handled exceptions
});

デフォルトでは、 morgan コンソールにのみ出力するので、取得できるストリーム関数を定義しましょう morgan-生成された出力 winston ログファイル。 を使用します info レベルは、出力が両方のトランスポート(ファイルとコンソール)によって取得されるようにします。

〜/ myApp / config / winston.js
...
logger.stream = {
  write: function(message, encoding) {
    logger.info(message);
  },
};

最後に、ロガーをエクスポートして、アプリケーションの他の部分で使用できるようにします。

〜/ myApp / config / winston.js
...
module.exports = logger;

完成 winston 構成ファイルは次のようになります。

〜/ myApp / config / winston.js
var appRoot = require('app-root-path');
var winston = require('winston');

// define the custom settings for each transport (file, console)
var options = {
  file: {
    level: 'info',
    filename: `${appRoot}/logs/app.log`,
    handleExceptions: true,
    json: true,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
    colorize: false,
  },
  console: {
    level: 'debug',
    handleExceptions: true,
    json: false,
    colorize: true,
  },
};

// instantiate a new Winston Logger with the settings defined above
var logger = new winston.Logger({
  transports: [
    new winston.transports.File(options.file),
    new winston.transports.Console(options.console)
  ],
  exitOnError: false, // do not exit on handled exceptions
});

// create a stream object with a 'write' function that will be used by `morgan`
logger.stream = {
  write: function(message, encoding) {
    // use the 'info' log level so the output will be picked up by both transports (file and console)
    logger.info(message);
  },
};

module.exports = logger;

終了してファイルを保存します。

これでロガーが構成されましたが、アプリケーションはまだロガーやその使用方法を認識していません。 次に、ロガーをアプリケーションと統合します。

ステップ4—Winstonとアプリケーションの統合

ロガーをアプリケーションで動作させるには、作成する必要があります express それを認識して。 ステップ2で、 express 構成はにあります app.js、それでは、ロガーをこのファイルにインポートしましょう。 次のコマンドを実行して、編集用にファイルを開きます。

  1. nano ~/myApp/app.js

輸入 winston 他のrequireステートメントを含むファイルの先頭近く:

〜/ myApp / app.js
...
var winston = require('./config/winston');
...

実際に使用する最初の場所 winstonmorgan. を使用します stream オプションを選択し、その一部として作成したストリームインターフェイスに設定します。 winston 構成。 これを行うには、次の行を見つけます。

〜/ myApp / app.js
...
app.use(morgan('combined'));
...

これに変更します:

〜/ myApp / app.js
...
app.use(morgan('combined', { stream: winston.stream }));
...

終了してファイルを保存します。

ログデータを表示する準備ができました。 Webブラウザでページをリロードすると、SSHセッションAのコンソールに次のようなものが表示されます。

Output
[nodemon] restarting due to changes... [nodemon] starting `node bin/www` info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:29:36 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:29:37 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"

ここには2つのログエントリがあります。1つはHTMLページへのリクエスト用で、もう1つは付随するスタイルシート用です。 各トランスポートは処理するように構成されているため info レベルのログデータの場合、次の場所にあるファイルトランスポートにも同様の情報が表示されます。 ~/myApp/logs/app.log. ただし、ファイルトランスポートの出力は、指定したため、JSONオブジェクトとして記述する必要があります。 json: true ファイルトランスポート構成で。 JSONの詳細については、JSONチュートリアルの概要をご覧ください。 ログファイルの内容を表示するには、次のコマンドを実行します。

  1. tail ~/myApp/logs/app.log

次のようなものが表示されます。

{"level":"info","message":"::ffff:72.80.124.207 - - [07/Mar/2018:17:29:36 +0000] \"GET / HTTP/1.1\" 304 - \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\"\n","timestamp":"2018-03-07T17:29:36.962Z"}
{"level":"info","message":"::ffff:72.80.124.207 - - [07/Mar/2018:17:29:37 +0000] \"GET /stylesheets/style.css HTTP/1.1\" 304 - \"http://167.99.4.120:3000/\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\"\n","timestamp":"2018-03-07T17:29:37.067Z"}

これまでのところ、ロガーはHTTPリクエストと関連データのみを記録しています。 これはログに記録する非常に重要な情報ですが、カスタムログメッセージを記録するにはどうすればよいですか? たとえば、エラーの記録やデータベースクエリのパフォーマンスのプロファイリングなどにこの機能が必要になる場合があります。 これを行う方法を説明するために、エラーハンドラルートからロガーを呼び出しましょう。

The express-generator パッケージにはデフォルトで404および500エラーハンドラルートが含まれているため、これを使用します。 を開きます ~/myApp/app.js ファイル:

  1. nano ~/myApp/app.js

次のようなファイルの下部にあるコードブロックを見つけます。

〜/ myApp / app.js
...
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
...

これは、最終的にエラー応答をクライアントに送り返す最終的なエラー処理ルートです。 すべてのサーバー側エラーはこのルートを介して実行されるため、これを含めるのに適した場所です。 winston ロガー。

現在エラーを処理しているので、 error ログレベル。 繰り返しますが、両方のトランスポートはログに記録するように構成されています error レベルメッセージなので、コンソールとファイルログに出力が表示されます。 ログには必要なものをすべて含めることができるため、次のような有用な情報を必ず含めてください。

  • err.status-HTTPエラーステータスコード。 まだ存在しない場合は、デフォルトで500になります。
  • err.message-エラーの詳細。
  • req.originalUrl-要求されたURL。
  • req.path-リクエストURLのパス部分。
  • req.method -リクエストのHTTPメソッド(GET、POST、PUTなど)。
  • req.ip-リクエストのリモートIPアドレス。

次のようにエラーハンドラルートを更新します。

〜/ myApp / app.js
...
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // add this line to include winston logging
  winston.error(`${err.status || 500} - ${err.message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
...

終了してファイルを保存します。

これをテストするために、存在しないプロジェクトのページにアクセスしてみましょう。これにより、404エラーがスローされます。 Webブラウザーに戻り、次のURLをロードしてみます。 http://your_server_ip:3000/foo. によって作成されたボイラープレートのおかげで、アプリケーションはすでにそのようなエラーに応答するように設定されています express-generator. ブラウザに次のようなエラーメッセージが表示されるはずです(エラーメッセージは表示されているものよりも詳細な場合があります)。

ここで、SSHセッションAのコンソールをもう一度見てください。 エラーのログエントリがあるはずです。色付け設定のおかげで、簡単に見つけることができます。

Output
[nodemon] starting `node bin/www` error: 404 - Not Found - /foo - GET - ::ffff:72.80.124.207 info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:40:11 +0000] "GET /foo HTTP/1.1" 404 985 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36" info: ::ffff:72.80.124.207 - - [07/Mar/2018:17:40:11 +0000] "GET /stylesheets/style.css HTTP/1.1" 304 - "http://167.99.4.120:3000/foo" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"

ファイルロガーについては、 tail コマンドを再度実行すると、新しいログレコードが表示されます。

  1. tail ~/myApp/logs/app.log

次のようなメッセージが表示されます。

{"level":"error","message":"404 - Not Found - /foo - GET - ::ffff:72.80.124.207","timestamp":"2018-03-07T17:40:10.622Z"}

エラーメッセージには、具体的に指示したすべてのデータが含まれています winston エラーステータス(404-見つかりません)、要求されたURL(localhost / foo)、要求メソッド(GET)、要求を行ったIPアドレス、および要求時のタイムスタンプを含む、エラーハンドラーの一部としてログに記録します。作られた。

結論

このチュートリアルでは、単純なNode.js Webアプリケーションを構築し、アプリケーションのパフォーマンスに関する洞察を提供する効果的なツールとして機能するWinstonロギングソリューションを統合しました。 特にニーズがより複雑になるにつれて、アプリケーション用の堅牢なロギングソリューションを構築するためにさらに多くのことを行うことができます。 時間をかけて、これらの他のドキュメントのいくつかを確認することをお勧めします。