9

一般的に受け入れられているように見えますが、私が実際に乗り越えることができない2つのステートメントを次に示します。

1)Scalaの名前によるパラメーターは、これまでにない厄介なlog4jの使用パターンを適切に置き換えます。

if (l.isDebugEnabled() ) { 
      logger.debug("expensive string representation, eg: godObject.toString()") 
   }

by-name-parameter(Scala固有の言語機能)はメソッド呼び出しの前に評価されないためです。

2)ただし、この問題は、slf4fのパラメーター化されたロギングによって解決されます。

logger.debug("expensive string representation, eg {}:", godObject[.toString()]);

では、これはどのように機能しますか?「デバッグ」メソッドの実行前にパラメーターの評価を妨げる、slf4jライブラリーに関連する低レベルの魔法はありますか?(それも可能ですか?図書館は言語のそのような基本的な側面に影響を与えることができますか?)

それとも、文字列ではなく、オブジェクトがメソッドに渡されるという単純な事実ですか?(そして、該当する場合は、そのオブジェクトのtoString()がdebug()メソッド自体で呼び出される可能性があります)。

しかし、それでは、log4jにも当てはまりませんか?(オブジェクトパラメータを持つメソッドがあります)。そして、これは、上記のコードのように文字列を渡すと、log4jと同じように動作することを意味しませんか?

私はこの問題に光を当ててもらいたいと思っています。

ありがとう!

4

1 に答える 1

26

slf4j には魔法はありません。ロギングの問題は、ロギングしたい場合は

logger.debug("expensive string representation: " + godObject)

次に、ロガーでデバッグ レベルが有効になっているかどうかに関係なく、godObject.toString()高価な操作になる可能性のある操作と、文字列の連結を常に評価しました。これは単純に、Java (およびほとんどの言語) では引数が関数に渡される前に評価されるという事実によるものです。

これが slf4j が導入された理由ですlogger.debug(String msg, Object arg)(およびより多くの引数のための他のバリアント)。全体的な考え方は、安価な引数をdebug関数に渡すことです。関数はそれらを呼び出しtoString、デバッグ レベルがオンの場合にのみそれらをメッセージに結合します。

呼び出すことによって注意してください

logger.debug("expensive string representation, eg: {}", godObject.toString());

この方法では、デバッグ レベルに関係なく、godObjectに渡す前に常に変換するため、この利点が大幅に減少します。debugのみを使用する必要があります

logger.debug("expensive string representation, eg: {}", godObject);

ただし、これはまだ理想的ではありません。呼び出しtoStringと文字列の連結を省くだけです。ただし、ログ メッセージを作成するために他のコストのかかる処理が必要な場合は、役に立ちません。expensiveMethodメッセージを作成するために何かを呼び出す必要がある場合のように:

logger.debug("expensive method, eg: {}",
    godObject.expensiveMethod());

thenexpensiveMethodは、 に渡される前に常に評価されloggerます。これを slf4j で効率的に機能させるには、次の方法に頼る必要があります。

if (logger.isDebugEnabled())
    logger.debug("expensive method, eg: {}",
        godObject.expensiveMethod());

Scala の名前による呼び出しは、任意のコードを関数オブジェクトにラップし、必要な場合にのみそのコードを評価できるため、この点で非常に役立ちます。これはまさに私たちが必要としているものです。たとえば、 slf4sを見てみましょう 。このライブラリは次のようなメソッドを公開しています

def debug(msg: => String) { ... }

slf4j のような引数がないのはなぜLoggerですか? もう必要ないからです。私たちはちょうど書くことができます

logger.debug("expensive representation, eg: " +
    godObject.expensiveMethod())

メッセージとその引数を渡すのではなく、メッセージに評価されるコードの一部を直接渡します。ただし、ロガーがそうすることにした場合のみ。デバッグ レベルがオンになっていない場合、その中にあるものは何もlogger.debug(...)評価されず、すべてがスキップされます。どちらexpensiveMethodも呼び出されず、toString呼び出しや文字列連結も発生しません。したがって、このアプローチは最も一般的で柔軟性があります。どんなに複雑であっても、 Stringtoに評価される任意の式を渡すことができます。debug

于 2012-11-02T18:57:26.820 に答える