Node.jsでのログインについて

まず、すべての開発者がこれについて知っておくべきことを繰り返します。 保護する必要がある





なぜログインする必要があるのですか



ステータスを表示するGUIを持たないサーバーアプリケーションを起動しましたが、本当に知りたいです。 最も単純で最も明白な解決策は、どこかにメッセージを表示することです-stdout / stderr、ファイル、syslog、より変なもの。 これはロギングです(ありがとうございました)。



ロギングを使用して解決できる主なタスクをリストします。



  1. 動作とパフォーマンスの分析。 ここで、パフォーマンス分析にはプローブを使用することをお勧めします(例: twitter zipkinはコード内のサンプルを介してデータを受信します)。 行動とは、現在起こっているすべてのことを指します。
  2. 問題の分析と診断。 ここで、アプリケーションの重大な状況が1/0であることは明らかです(いつ発生したかは関係ありません。アプリケーションが死にかけようとしています)。 そうです-それを誓います。 これについては、以下で詳しく説明します。
  3. あらゆる種類の左利きのユースケース。




記録方法



たくさんと少しの両方でログに書き込む必要があります。 アプリケーションの現在の状態を理解することはほとんどないので、アプリケーションがクラッシュした場合にその理由を理解することはできません。



つまり、何が起きているのかを理解するために、 あなた自身が必要と考えるものを書きます。 ただし、ロギングはアプリケーションリソースを消費することを強調する必要があります。したがって、関与する必要はありません。アプリケーションを一度見たところ、ロギングがパフォーマンスの約50%を消費しました(もちろん、これはPPCで行う必要はありません)。



エラー/例外などが発生した場合、その理由を理解する必要があります。 この瞬間に、なぜこのようなことが起こったのかを理解するために必要なすべて(はい、絶対にすべて)をログに書き込みます(ここでは、たくさん書く必要があります-恥ずかしがらないでください)。



ログレベル



明らかに、すべてのメッセージが同等に重要なわけではありません。 通常、ほとんどのアプリケーションでは5つのログレベルで十分です。slf4jで使用するレベルの名前を使用します。



  1. エラー-緊急時のアプリケーションは、続行するには人の注意が必要です。 まれにしか表示されませんが、適切に表示されます。 非常に低レベルのものや未処理の例外に使用します
  2. 警告-通常のシナリオではなく、異常なことが起こりましたが、アプリケーションはスマートであり、それ自体で作業を復元しました。 このレベルをエラーハンドラーで使用します。
  3. 情報-現在何が起こっているのか
  4. デバッグ-現在何が起こっているか、詳細
  5. トレース-Twitterのように書き込みます。




さらに、上記を考慮すると、node.jsで試したロガーとそれらの何が問題なのかを少し比較します。



log4js



これが、log4jに少なくともある程度似ていることを期待して、私が最初に見たものです。



小さな例:

var log4js = require('log4js'); var logger = log4js.getLogger(); logger.debug("Some debug messages");
      
      





コンソールにカラーメッセージが表示されます。

 [2014-01-13 20:41:22.604] [DEBUG] [default] - Some debug messages
      
      





このロガーには必要な最小値があります。 レベルとカテゴリ(ロガー名)、メッセージ時間、およびそれを変更する機能によるメッセージのフィルタリングがあります。 Util.formatはメッセージの表示に使用されます-したがって、console.logと同じフォーマットオプションがサポートされます。



ウィンストン



SOでよく推奨されます。 私は個人的にそれを誰にも勧めません。

例:

 var winston = require('winston'); winston.info('Hello distributed log files!');
      
      





コンソールには何が表示されます:

 info: Hello distributed log files!
      
      





この場所には小さな記録があり、ウィンストンは記録時間を与えることができません、Keennのおかげで、まだ可能であることが判明しましたが、これらのオプション(タイムスタンプ:トランスポートの場合はtrue)はデフォルトでオフになっていますが、これは非常に奇妙です。



バンヤン



以前の2つのライブラリとは異なり、このロガーはテキストではなくJSONを生成します。 作成者は、ログがまだマシン(ログコレクター)によって解析されていると判断し、それをマシンで読み取り可能な形式にしました。 これは、最初のログ記録シナリオにうまく適合します(明らかに、手でサンプルを収集することは、少なくとも愚かなことです)が、コレクターが常に使用されるわけではありません。 個人的に不思議に思われた、または言って良いことに、失敗した解決策:

  1. 私の意見ではロギングの最も合理的な使用である2番目のシナリオのJSONは、アセンブラーコードのC ++コードでエラーを探す方法です。 ログは人に読まれます。 アプリケーションが小さい場合、ログコレクターは冗長であり、表示される場合は、そのハンドラーを追加するだけです。
  2. コードの構成について話すと、ロガーハンドラーが吐き出され、ハンドラーの責任です-つまり、理論的には、JSON出力は、独自のハンドラー/フォーマッターを作成できる任意のライブラリに固定できます。
  3. Bunyanには、カスタムタイプのシリアライザーという1つの機能があります。 オブジェクトのバンドルがメッセージとともにロガーに供給され、オブジェクトがシリアル化されます。 別の角度から見た場合:

    シリアル化はオブジェクトの単なるJSON表現です。 各オブジェクトはプロトタイプでtoJSONメソッドを決定でき、 JSON.stringifyで呼び出されます -これはシリアライザーです。 今、それをどうやって取り出すか-絶対にすべてのロガーで、特別なフラグ(util.formatの場合は%j)を使用してオブジェクトのjson表現を表示できます。 つまり、この機能は非常に明白なようです。


私は正直に言って、このロガーを使用した経験はほとんどありません(最初にそれを台無しにしようとしました-すべて同じ喜びがそれを使用しています)、彼らが私に見せて/見せて/それでクールなものに鼻を突くなら、私は喜んで耳を傾け、メモします ロガーの階層の単純な組織があることに気づきましたが、それを使用するのは便利ではないようでした。



インテル



これは私が出会った中で最高のロギングライブラリです。 設定に関しては、私はそれについて不満はありませんでした。 彼女が好きだった理由:

  1. すでに述べたように、彼女は非常に便利な構成を備えており、すべてを1か所で構成できます。 ロガーにはハンドラーがあり、ハンドラーにはメッセージフォーマッターがあり、メッセージとレベルによるフィルターがあります。 ほぼおとぎ話。
  2. たとえば、slf4jに付属しているロガーの階層はこれを当たり前のことと考えていますが、通常はこのlibでのみ実装されていました。 ロガー階層とは:

    各ロガーには親があり(ロガーのフルネームはすべての親のポイントを再カウントすることによって設定されます)、親の構成を設定し、すべての子が自動的に受信するようにオプションを設定できます(ログ伝播)。 つまり、たとえば、複数の親ロガーを作成し、それらのハンドラーを設定して(たとえば、ERRORおよびWARNレベルに電子メールを送信)、すべての子がそれらを使用しますが、さらに、何らかの種類のログツリーをミュートする必要がある場合は、構成を特殊化しますそのフルパス。 そして、このすべてを1か所で一度。
  3. 標準コンソールの非常に合理的な代替。 現在の作業ディレクトリを基準にしたパスが許可されているため、console.log出力を簡単に構成し、ロガーパンを取得できます。


短時間使用した後(このプロジェクトでは、他の人と同じように書式設定にほとんど注意が払われていないことに気付きました)、ミリ秒を出力する機能、書式設定されたエラー出力のサポートを追加するためにいくつかのプルリクエストを行いましたが、著者と4-5プルリクエストを行うと、作者が自分の道を歩むことを望んでいることが明らかになり、私が夢見たものを追加してプロジェクトを分岐させました。

コードを掘り下げてみると、筆者はベンチマークのためにコードを最適化していることに気付きました 。 私はそのようなことについて自分の意見を自分に任せたほうが良いでしょう

lib自体で変更したもので、ハンドラーはそのままです。

  1. 私はベンチマークのためにそのような最適化をすべて捨てました-そのようなことを書くことはあなた自身を尊重しません。
  2. Intelのメッセージの形式:オブジェクトレコードのフィールドのタイプ(例: '[%(date)s]%(name)s ::%(message)s')を示す必要がありますが、これらのフィールドのタイプはわかっているため、それらを指定する必要があります。 代わりに、ログバックからメッセージ形式を取りました。
  3. ロギング中に引数をフォーマットするには、独自のキーを使用して独自のアナログutil.formatを使用します。これは、コンソールを置き換えるときにも使用されます。つまり、サードパーティのlibがコンソールで期待するものを取得できないと書いた場合にも使用されます。 当然、util.formatに置き換えられました
  4. プロファイリングの後、メッセージのフォーマットに常に時間がかかることが明らかになりました。 形式は通常1回設定されるため、新しい関数を使用して行われた最適化は合理的です。形式はすべての呼び出しではなく1回収集されます。


まだ小さなことがいくつかありますが、それは何らかのPRであり、比較ではありません。

いくつかの不可解な違いを示すために-速度の小さな測定値( ベンチマークコード 、すべてのバージョンが最新です)。 logger.infoを(メッセージと共に)印刷するだけです:

 $ node benchmark/logging.js console.info x 1,471,685 ops/sec ±0.79% (95 runs sampled) rufus.info x 200,641 ops/sec ±1.04% (84 runs sampled) winston.info x 65,567 ops/sec ±0.80% (96 runs sampled) intel.info x 56,117 ops/sec ±1.51% (92 runs sampled) bunyan.info x 86,970 ops/sec ±1.71% (81 runs sampled) log4js.info x 45,351 ops/sec ±3.25% (79 runs sampled) Fastest is console.info
      
      





このメッセージ形式では、[[%date]%logger ::%message 'であり、常に期待するのが妥当です。 最適化の力を最大限に活用するために、Intelの標準メッセージに置き換えてみましょう。

 $ node benchmark/logging.js console.info x 1,569,375 ops/sec ±0.66% (95 runs sampled) rufus.info x 199,138 ops/sec ±0.81% (97 runs sampled) winston.info x 66,864 ops/sec ±0.84% (91 runs sampled) intel.info x 173,483 ops/sec ±5.64% (59 runs sampled) bunyan.info x 86,357 ops/sec ±1.02% (94 runs sampled) log4js.info x 49,978 ops/sec ±2.29% (81 runs sampled) Fastest is console.info
      
      





興味深い変化。

それだけです。 誰もが興味を持っている場合- フォーク (私は自分の自由な時間に書いたように、機能リクエストを受け入れない可能性が高いです、バグとプルリクエストで歓迎します)。

いつものように、コメントで自分にとって新しいものを見つけたいと思っています。 エラーはPMでお願いします。



All Articles