Suche…


Verwenden des Standard-Loggers

Dieses Beispiel zeigt die Verwendung der Standardprotokollierungs-API.

import java.util.logging.Level;
import java.util.logging.Logger;

public class MyClass {
    
    // retrieve the logger for the current class
    private static final Logger LOG = Logger.getLogger(MyClass.class.getName());
    
    public void foo() {
        LOG.info("A log message");
        LOG.log(Level.INFO, "Another log message");

        LOG.fine("A fine message");
    
        // logging an exception
        try {
            // code might throw an exception
        } catch (SomeException ex) {
            // log a warning printing "Something went wrong"
            // together with the exception message and stacktrace
            LOG.log(Level.WARNING, "Something went wrong", ex);
        }

        String s = "Hello World!";

        // logging an object
        LOG.log(Level.FINER, "String s: {0}", s);

        // logging several objects
        LOG.log(Level.FINEST, "String s: {0} has length {1}", new Object[]{s, s.length()});
    }

}

Protokollierungsstufen

Java Logging Api verfügt über 7 Stufen . Die Ebenen in absteigender Reihenfolge sind:

  • SEVERE (höchster Wert)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (niedrigster Wert)

Die Standardstufe ist INFO (dies hängt jedoch vom System ab und verwendet eine virtuelle Maschine).

Hinweis : Es gibt auch die Pegel OFF (kann zum Deaktivieren der Protokollierung verwendet werden) und ALL (die Seite OFF ).

Codebeispiel dafür:

import java.util.logging.Logger;

public class Levels {
    private static final Logger logger = Logger.getLogger(Levels.class.getName());

    public static void main(String[] args) {

        logger.severe("Message logged by SEVERE");
        logger.warning("Message logged by WARNING");
        logger.info("Message logged by INFO");
        logger.config("Message logged by CONFIG");
        logger.fine("Message logged by FINE");
        logger.finer("Message logged by FINER");
        logger.finest("Message logged by FINEST");

        // All of above methods are really just shortcut for
        // public void log(Level level, String msg):
        logger.log(Level.FINEST, "Message logged by FINEST");
    }
}

Wenn diese Klasse standardmäßig ausgeführt wird, werden nur Nachrichten mit einer höheren Stufe als CONFIG :

Jul 23, 2016 9:16:11 PM LevelsExample main
SEVERE: Message logged by SEVERE
Jul 23, 2016 9:16:11 PM LevelsExample main
WARNING: Message logged by WARNING
Jul 23, 2016 9:16:11 PM LevelsExample main
INFO: Message logged by INFO

Komplexe Meldungen protokollieren (effizient)

Schauen wir uns ein Protokollbeispiel an, das Sie in vielen Programmen sehen können:

public class LoggingComplex {
    
    private static final Logger logger = 
        Logger.getLogger(LoggingComplex.class.getName());

    private int total = 50, orders = 20;
    private String username = "Bob";

    public void takeOrder() {
        // (...) making some stuff
        logger.fine(String.format("User %s ordered %d things (%d in total)", 
                                  username, orders, total));
        // (...) some other stuff
    }

    // some other methods and calculations
}

Das obige Beispiel sieht perfekt aus, aber viele Programmierer vergessen, dass Java VM eine Stack-Maschine ist. Das bedeutet, dass alle Parameter der Methode vor der Ausführung der Methode berechnet werden.

Diese Tatsache ist für die Protokollierung in Java von entscheidender Bedeutung, insbesondere für die Protokollierung von FINER in niedrigen Stufen wie FINE , FINER , FINEST die standardmäßig deaktiviert sind. Schauen wir uns den Java-Bytecode für die takeOrder() -Methode an.

Das Ergebnis für javap -c LoggingComplex.class lautet javap -c LoggingComplex.class so:

public void takeOrder();
    Code:
       0: getstatic     #27 // Field logger:Ljava/util/logging/Logger;
       3: ldc           #45 // String User %s ordered %d things (%d in total)
       5: iconst_3
       6: anewarray     #3  // class java/lang/Object
       9: dup
      10: iconst_0
      11: aload_0
      12: getfield      #40 // Field username:Ljava/lang/String;
      15: aastore
      16: dup
      17: iconst_1
      18: aload_0
      19: getfield      #36 // Field orders:I
      22: invokestatic  #47 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      25: aastore
      26: dup
      27: iconst_2
      28: aload_0
      29: getfield      #34 // Field total:I
      32: invokestatic  #47 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      35: aastore
      36: invokestatic  #53 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
      39: invokevirtual #59 // Method java/util/logging/Logger.fine:(Ljava/lang/String;)V
      42: return

Zeile 39 führt die eigentliche Protokollierung aus. Alle vorherigen Arbeiten (Laden von Variablen, Erstellen neuer Objekte, Verketten von Strings in der format ) können nichts ausrichten, wenn die Protokollierungsstufe höher als FINE (und standardmäßig) eingestellt ist. Eine solche Protokollierung kann sehr ineffizient sein und unnötigen Speicher und Prozessorressourcen beanspruchen.

Deshalb sollten Sie fragen, ob die gewünschte Ebene aktiviert ist.

Der richtige Weg sollte sein:

public void takeOrder() {
    // making some stuff
    if (logger.isLoggable(Level.FINE)) {
        // no action taken when there's no need for it
        logger.fine(String.format("User %s ordered %d things (%d in total)",
                                  username, orders, total));
    }
    // some other stuff
}

Seit Java 8:

Die Logger-Klasse verfügt über zusätzliche Methoden, die einen Supplier<String> als Parameter verwenden, der einfach von einem Lambda bereitgestellt werden kann:

public void takeOrder() {
    // making some stuff
    logger.fine(() -> String.format("User %s ordered %d things (%d in total)",
            username, orders, total));
    // some other stuff
}

Die Methode " get() Suppliers get() in diesem Fall das Lambda) wird nur aufgerufen, wenn die entsprechende Ebene aktiviert ist und die if Konstruktion nicht mehr benötigt wird.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow