Szukaj…


Korzystanie z domyślnego rejestratora

Ten przykład pokazuje, jak korzystać z domyślnego interfejsu API rejestrowania.

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()});
    }

}

Poziomy rejestrowania

Interfejs Java Logging Api ma 7 poziomów . Poziomy w kolejności malejącej to:

  • SEVERE (najwyższa wartość)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (najniższa wartość)

Poziom domyślny to INFO (ale zależy to od systemu i używanej maszyny wirtualnej).

Uwaga : Istnieją również poziomy OFF (Można użyć do wyłączenia rejestrowania) i ALL (przeciwieństwo OFF .).

Przykład kodu dla tego:

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");
    }
}

Domyślnie uruchomienie tej klasy wyświetli tylko komunikaty o poziomie wyższym niż 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

Rejestrowanie złożonych wiadomości (efektywnie)

Spójrzmy na przykład rejestrowania, który można zobaczyć w wielu programach:

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
}

Powyższy przykład wygląda doskonale, ale wielu programistów zapomina, że Java VM jest maszyną stosową. Oznacza to, że wszystkie parametry metody są obliczane przed wykonaniem metody.

Fakt ten ma zasadnicze znaczenie dla rejestrowania w Javie, szczególnie zalogowaniu coś w niskich jak FINE , FINER , FINEST które są domyślnie wyłączone. Spójrzmy na kod bajtowy Java dla metody takeOrder() .

Wynik dla javap -c LoggingComplex.class jest javap -c LoggingComplex.class taki:

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

Linia 39 uruchamia rejestrowanie. Cała poprzednia praca (ładowanie zmiennych, tworzenie nowych obiektów, łączenie łańcuchów w metodzie format ) może być bezużyteczna, jeśli poziom rejestrowania jest ustawiony wyżej niż FINE (i domyślnie tak jest). Takie rejestrowanie może być bardzo nieefektywne, pochłaniając niepotrzebne zasoby pamięci i procesora.

Dlatego powinieneś zapytać, czy poziom, którego chcesz użyć, jest włączony.

Właściwą drogą powinno być:

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
}

Od wersji Java 8:

Klasa Logger ma dodatkowe metody, które przyjmują parametr Supplier<String> jako parametr, który można po prostu podać za pomocą lambda:

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

Metoda get() Dostawcy - w tym przypadku lambda - jest wywoływana tylko wtedy, gdy odpowiedni poziom jest włączony, a więc if konstrukcja nie jest już potrzebna.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow