Buscar..


Usando el registrador predeterminado

Este ejemplo muestra cómo usar la api de registro predeterminada.

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

}

Niveles de registro

Java Logging Api tiene 7 niveles . Los niveles en orden descendente son:

  • SEVERE (valor más alto)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (valor más bajo)

El nivel predeterminado es INFO (pero esto depende del sistema y utiliza una máquina virtual).

Nota : También hay niveles OFF (se pueden usar para desactivar el registro) y ALL (el opuesto de OFF ).

Código de ejemplo para esto:

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

Por defecto, ejecutar esta clase solo generará mensajes con un nivel más alto que 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

Registro de mensajes complejos (eficientemente)

Veamos una muestra de registro que puede ver en muchos programas:

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
}

El ejemplo anterior se ve perfectamente bien, pero muchos programadores olvidan que Java VM es una máquina de pila. Esto significa que todos los parámetros del método se calculan antes de ejecutar el método.

Este hecho es crucial para el registro en Java, especialmente para registrar algo en niveles bajos, como FINE , FINER , FINEST que son desactivados por defecto. Veamos el takeOrder() Java para el método takeOrder() .

El resultado para javap -c LoggingComplex.class es algo como esto:

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

La línea 39 ejecuta el registro real. Todo el trabajo anterior (cargar variables, crear nuevos objetos, concatenar cadenas en el método de format ) puede ser en vano si el nivel de registro se establece más alto que FINE (y por defecto lo es). Dicho registro puede ser muy ineficiente y consumir recursos innecesarios de memoria y procesador.

Por eso debe preguntar si el nivel que desea usar está habilitado.

La forma correcta debe ser:

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
}

Desde Java 8:

La clase Logger tiene métodos adicionales que toman un Supplier<String> como parámetro, que simplemente puede proporcionar un 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
}

El método de get() Proveedores get() en este caso, la lambda, solo se llama cuando el nivel correspondiente está habilitado y por lo tanto la construcción if ya no es necesaria.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow