Parametrisierte Protokollierung in slf4j - wie wird es mit den Parametern von scala verglichen?

8

Hier sind zwei Aussagen, die allgemein akzeptiert zu sein scheinen, aber die ich nicht wirklich überwinden kann:

1) Scalas Vornamen-Parameter ersetzen anmutig das immer lästige log4j-Nutzungsmuster:

%Vor%

, weil der Name-Name-Parameter (eine Scala-spezifische Sprachfunktion ) nicht vor dem Methodenaufruf ausgewertet wird.

2) Dieses Problem wird jedoch durch die parametrisierte Protokollierung in slf4f gelöst:

%Vor%

Also, wie funktioniert das? Gibt es in der Bibliothek slf4j eine Low-Level-Magie, die die Auswertung des Parameters vor der Ausführung der "Debug" -Methode verhindert? (Ist das überhaupt möglich? Kann eine Bibliothek einen so grundlegenden Aspekt der Sprache beeinflussen?)

Oder ist es nur die einfache Tatsache, dass ein Objekt an die Methode übergeben wird - und nicht an einen String? (und möglicherweise wird toString () dieses Objekts in der debug () -Methode selbst aufgerufen, falls zutreffend).

Aber stimmt das nicht auch für log4j? (Es hat Methoden mit Objektparametern). Und würde das nicht bedeuten, dass, wenn Sie eine Zeichenfolge übergeben - wie im obigen Code - würde es sich genauso verhalten wie log4j?

Ich würde wirklich gerne etwas Licht in diese Angelegenheit werfen.

Danke!

    
teo 02.11.2012, 16:21
quelle

1 Antwort

24

Es gibt keine Magie in slf4j. Das Problem mit der Protokollierung war, dass, wenn Sie sich anmelden wollten, sagen wir

%Vor%

dann, egal ob die Debug-Ebene im Logger aktiviert war oder nicht, haben Sie immer godObject.toString() ausgewertet, was eine teure Operation sein kann, und dann auch eine Verkettung. Dies ergibt sich einfach aus der Tatsache, dass in Java (und den meisten Sprachen) Argumente ausgewertet werden, bevor sie an eine Funktion übergeben werden.

Deshalb hat slf4j logger.debug(String msg, Object arg) (und andere Varianten für weitere Argumente) eingeführt. Die Idee ist, dass Sie billige Argumente an die debug -Funktion übergeben und toString für sie aufrufen und sie nur dann zu einer Nachricht zusammenfassen, wenn der Debug-Level aktiviert ist.

Beachten Sie, dass Sie

aufrufen %Vor%

Sie reduzieren diesen Vorteil drastisch, da Sie auf diese Weise godObject die ganze Zeit konvertieren, bevor Sie es an debug übergeben, unabhängig davon, welche Debug-Ebene aktiviert ist. Sie sollten nur

verwenden %Vor%

Dies ist jedoch immer noch nicht ideal. Es erspart nur den Aufruf von toString und String-Verkettung. Wenn Ihre Protokollierungsnachricht jedoch eine andere kostspielige Verarbeitung erfordert, um die Nachricht zu erstellen, wird es nicht helfen. Zum Beispiel, wenn Sie expensiveMethod aufrufen müssen, um die Nachricht zu erstellen:

%Vor%

dann wird expensiveMethod immer ausgewertet, bevor es an logger übergeben wird. Damit dies effizient mit slf4j funktioniert, müssen Sie immer noch auf

zurückgreifen %Vor%

Der Call-by-Name von Scala hilft in dieser Hinsicht sehr, da Sie damit ein beliebiges Stück Code in ein Funktionsobjekt einbinden und diesen Code nur bei Bedarf auswerten können. Genau das brauchen wir. Schauen wir uns zum Beispiel slf4s an. Diese Bibliothek macht Methoden wie

%Vor%

Warum keine Argumente wie in% sf4j Logger ? Weil wir sie nicht mehr brauchen. Wir können nur schreiben

%Vor%

Wir übergeben keine Nachricht und ihre Argumente, wir leiten direkt einen Teil des Codes weiter, der für die Nachricht ausgewertet wird. Aber nur wenn der Logger sich dazu entschließt. Wenn der Debug-Level nicht aktiviert ist, wird nichts, was innerhalb von logger.debug(...) liegt, ausgewertet. Das Ganze wird einfach übersprungen. Weder expensiveMethod wird aufgerufen noch irgendwelche toString Aufrufe oder String-Verkettungen. Dieser Ansatz ist also am allgemeinsten und am flexibelsten. Sie können einen beliebigen Ausdruck übergeben, der ein String bis debug ergibt, unabhängig davon, wie komplex er ist.

    
Petr Pudlák 02.11.2012, 18:57
quelle