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
呼び出しや文字列連結も発生しません。したがって、このアプローチは最も一般的で柔軟性があります。どんなに複雑であっても、 String
toに評価される任意の式を渡すことができます。debug