web-dev-qa-db-ja.com

slf4jを使用する場合でも、ログを保護する必要がありますか?

ここでの議論で私を助けてください.. :)

ここのslf4jサイト http://www.slf4j.org/faq.html#logging_performance は、パラメータ化されたロギングのため、ロギングガードが不要であることを示しています。つまり書く代わりに:

if(logger.isDebugEnabled()) {
  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}

あなたは逃げることができます:

Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);

これは本当に大丈夫ですか、それともtraceメソッドに渡される静的文字列を作成するコストは(それでも)低くなりますか?

35
Mark D

私は別の観点から私の2セントを入れてみます

正確にパラメータ化されたロギングの利点は何ですか?

toString() invocationstring concatenationを延期するだけです本当に必要になるまで、それはあなたが本当にメッセージを記録しなければならないときです。これにより、特定のロギング操作が無効になっているときにパフォーマンスが最適化されます。確認できない場合は SLF4Jのソースコード を確認してください。

パラメータ化されたロギングにより、すべてのケースでガードが役に立たなくなりますか?

番号。

ロギングガードが役立つのはどの場合ですか?

他に潜在的な高価な操作がある場合。

たとえば(この特定のロギング操作が無効になっている場合)、[ロギングガードなし

_logger.debug("User name: {}", getUserService().getCurrentUser());
_
  1. payコストをobj = getUserService().getCurrentUser()から
  2. "User name: " + obj.toString()からコストを節約します

ロギングガードを使用するの場合:

_if (logger.isDebugEnabled()) {
    logger.debug("User: {}", getUserService().getCurrentUser());
}
_
  1. 私たちはpayのコストをlogger.isDebugEnabled()
  2. saveコストをobj = getUserService().getCurrentUser()から(
  3. "User name: " + obj.toString()からコストを節約します

後者の場合、この特定のロギング操作が有効になっている場合、isDebugEnabled()を2回チェックすることで両方のコストを節約できます。

注:これは単なる例であり、ここで良い/悪い習慣について議論しようとするものではありません。

52
fglez

これらすべてのif(logger.isDebugEnabled()) {}の書き込みと読み取りには、節約するのと同じくらいの時間がかかります。

もちろん、logメソッドの呼び出しは無料ではありませんが、isDebugEnabled()の呼び出しについても同様です。したがって、このパターンを使用すると、アクティブなログステートメントごとに追加料金が発生します(ログフレームワークがレベルを2回チェックするため)。

また、コードが乱雑になります。

実際には、パフォーマンスのペナルティが気になるほど大きくはありません。

ロギングが遅すぎる場合は、いくつかのチェックを行わずにログイベントをキューにプッシュする非ブロッキングアペンダーを記述し、バックグラウンドスレッドを使用してそれらを処理します。

背景:標準のアペンダーはすべて同期されているため、マルチスレッドアプリケーションでログを記録すると、すべてのスレッドがログメッセージがファイルに書き込まれるのを待機する多数の小さな一時停止が発生する可能性があります。

18
Aaron Digulla

文字列が作成されるため、ガードは使用されません。

代わりに、entry[i].retrieveExtendedDebugInformation().formatNicely()のような、潜在的にコストのかかる引数式を回避するために通常使用されます。そのため、logbackは、ログメッセージが実際に出力されるときにのみ引数が評価されるようにしますが、log4jは常にdebug()を呼び出す前に引数を評価します。

ここでの唯一の候補はString.valueOf(entry[i])であり、これもそれほど高価ではないため、このガードはまったく不要であるという主張をすることができます。

8
wallenborn

次のようなロギングステートメントの問題:

logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));

これは、値をStringに連結するために多くの作業を行うため、デバッグログがオフの場合は使用されないということです。したがって、その場合は、この行を実行する前にデバッグログがオンになっているかどうかを確認することをお勧めします。パラメータを渡すだけの場合:

logger.debug("The entry is {}.", entry);

そうすれば、使用されないStringを不必要に作成する必要がなくなり、チェックも不要になります。メソッドに引数を渡すだけでは、オーバーヘッドはそれほど高くありません。

ロギングステートメントの引数に比較的高額な式がある場合でも、最初にロギングレベルを確認することが有益な場合があります。

4
Jesper

ifステートメントは使用しないでください。このようなコードを見るたびに

if (logger.isDebug()) {
   logger.debug("Of course it's debug {}", sadFace);
}

私は泣く。

静的文字列を作成するコストが非常に低く、99%のユーザーにとって重要ではないことを願っています。

3
Jeff Foster