Zoeken…


Het standaardlogboek gebruiken

Dit voorbeeld laat zien hoe de standaard logboek-API te gebruiken.

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

}

Logniveaus

Java Logging Api heeft 7 niveaus . De niveaus in aflopende volgorde zijn:

  • SEVERE (hoogste waarde)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (laagste waarde)

Het standaardniveau is INFO (maar dit is afhankelijk van het systeem en een virtuele machine).

Opmerking : Er zijn ook niveaus OFF (kan worden gebruikt om het uitloggen uit te schakelen) en ALL (tegenovergesteld aan OFF ).

Codevoorbeeld hiervoor:

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

Standaard zal deze klasse alleen berichten uitvoeren met een niveau hoger dan 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

Complexe berichten loggen (efficiënt)

Laten we eens kijken naar een voorbeeld van logboekregistratie dat u in veel programma's kunt zien:

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
}

Het bovenstaande voorbeeld ziet er prima uit, maar veel programmeurs vergeten dat Java VM een stapelmachine is. Dit betekent dat alle parameters van de methode worden berekend voordat de methode wordt uitgevoerd.

Dit feit is cruciaal voor het loggen in Java, vooral voor het loggen van iets in lage niveaus zoals FINE , FINER , FINEST die standaard zijn uitgeschakeld. Laten we Java-bytecode bekijken voor de methode takeOrder() .

Het resultaat voor javap -c LoggingComplex.class is zoiets als dit:

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

Regel 39 voert de daadwerkelijke registratie uit. Al het vorige werk (variabelen laden, nieuwe objecten maken, tekenreeksen samenvoegen in format ) kan voor niets zijn als het logniveau hoger is ingesteld dan FINE (en standaard is dat het). Zulke logboekregistratie kan erg inefficiënt zijn en onnodige geheugen- en processorbronnen in beslag nemen.

Daarom moet u vragen of het niveau dat u wilt gebruiken is ingeschakeld.

De juiste manier zou moeten zijn:

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
}

Sinds Java 8:

De Logger-klasse heeft aanvullende methoden die een Supplier<String> als parameter nemen, die eenvoudig door een lambda kunnen worden geleverd:

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

De Leveranciers get() methode - in dit geval de lambda - wordt alleen opgeroepen als de bijbehorende niveau is ingeschakeld en dus het if constructie niet meer nodig is.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow