Frage

Wie viele log4j Benutzer, wir oft Debug-Level-Protokollierung, die teuer ist zu bewerten. So wir schützen die Fälle mit Code wie:

if( _logger.isDebugEnabled )
  _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails())

Das ist jedoch hässlicher als ein reiner _logger.debug Anruf, und manchmal ist der Programmierer nicht die Auswertung realisieren könnte teuer werden.

Es scheint, wie es ziemlich einfach sein sollte, ein Programm zu schreiben, die eine kompilierte Glas und schützt alle _logger.debug mit dem isDebugEnabled Check ruft nimmt. Wir würden wahrscheinlich bereit sein, den zusätzlichen Aufwand zu akzeptieren, der in allen Fällen isDebugEnabled zu überprüfen.

Hat jemand diesen Ansatz versucht, oder ähnliche Nachbearbeitung eines Glas getan?

War es hilfreich?

Lösung

Haben Sie sich AspectJ ? Das unterstützt Aspekte Bytecode Weben verwendet wird, und kann Interceptions in eine zuvor kompilierte .jar-Datei .

Andere Tipps

Statt Blick auf das Glas zu modifizieren, ich nach einer Lösung suchen würde mit Bytecode Instrumentation . Das Problem wird sich die Teile des Codes zu identifizieren, um Sie in einem .isDebugEnabled() wickeln möchten -. Sie werden Objekte zu identifizieren, die nur für log4j Anrufungen verwendet werden

Ich glaube, eine gute Lösung wäre, dass würde der Code effizient sein wie .

Beachten Sie, dass log4j ist veraltet. Sein Autor selbst es gelassen wie es ist, zu vermeiden, Kompatibilität zu brechen, aber er schuf ein neues, SLF4J ( http: // www .slf4j.org / ). Er bietet sowohl eine Fassade und eine Implementierung gemäß der Unterscheidung commons-logging / log4j, aber ohne die Fehler der einzelnen ...

Ich glaube, dass in dieser neuen Protokollierungsfunktion können Sie Objektparameter an die Protokollierung senden, und dass das Niveau ausgewertet, bevor die Objekte konvertiert (in String oder aus anderen Gründen). Die Idee ist, ein Format-String und Parameter zu verwenden.


Unser Code verwendet nicht slf4j, aber wir Dienstprogramm Methoden, die das genau tun. Es ist in etwa wie folgt codiert (aus dem Gedächtnis):

    public enum LogLevel {
       FATAL, ERROR, WARNING, INFO, DEBUG;

       public void log(Logger logger, String format, Object... parameters) {
         if (isEnabled(logger)) {
            logImpl(logger, String.format(format, parameters));
         }
       }
       public boolean isEnabled(Logger logger) {
         switch(this) {
           case WARNING : return logger.isWarningEnabled();
           case INFO : return logger.isInfoEnabled();
           case DEBUG : return logger.isDebugEnabled();
           default: return true;
         }
       }
       private void logImpl(Logger logger, String message) {
         switch(this) {
           case WARNING : logger.warn(message);
           // other cases
         }
       }
    }

Es wird verwendet, wie:

     public void myMethod(Object param) {
       LogLevel.WARNING.log(LOGGER, "What is my message ....", "myMethod", param);
     }

UPDATE : Wenn Sie eine Methode im Protokoll rufen ...

  • Eine Möglichkeit ist toString Methode zu verwenden. Dies ist angemessen, , wenn Ihr Logging 'technische' ist, und wird auch verwendet werden beim Debuggen.

  • Wenn die Protokollierung funktionelle (nicht auf die developper gezielt), schlage ich vor, eine Schnittstelle zu definieren (in diesem Fall funktionell Sound ist, so dass es sinnvoll ist Bedeutung zu liefern) :

    public interface Detailable { // the name could also suggest logging?
      String getFullDetails();
    }
    

    Implementieren Sie diese Schnittstelle in jedem Objekt, das als Logging-Objekt übergeben werden müssen, mit einer komplexen Berechnung des Protokolls zu bauen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top