Los JavaDocs para eljava.util.logging.Level
estado:
Los niveles en orden descendente son:
SEVERE
(valor más alto)WARNING
INFO
CONFIG
FINE
FINER
FINEST
(valor más bajo)
Fuente
import java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
logger.setLevel(Level.FINER);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
Salida
Logging level is: FINER
Jun 11, 2011 9:39:23 PM LoggingLevelsBlunder main
INFO: 0 0
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 1 1
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 2 4
Press any key to continue . . .
Planteamiento del problema
Mi ejemplo establece el Level
to FINER
, por lo que esperaba ver 2 mensajes para cada bucle. En cambio, veo un solo mensaje para cada bucle ( Level.FINE
faltan los mensajes).
Pregunta
¿Qué necesita cambiar para ver la salida FINE
(, FINER
o FINEST
)?
Actualizar (solución)
Gracias a la respuesta de Vineet Reynolds , esta versión funciona según mis expectativas. Muestra 3 x INFO
mensajes y 3 x FINE
mensajes.
import java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
// LOG this level to the log
logger.setLevel(Level.FINER);
ConsoleHandler handler = new ConsoleHandler();
// PUBLISH this level
handler.setLevel(Level.FINER);
logger.addHandler(handler);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
java
logging
java.util.logging
Andrew Thompson
fuente
fuente
Respuestas:
Los registradores solo registran el mensaje, es decir, crean los registros de registro (o solicitudes de registro). No publican los mensajes a los destinos, de lo que se encargan los Handlers. Establecer el nivel de un registrador solo hace que cree registros que coincidan con ese nivel o más.
Es posible que esté usando un
ConsoleHandler
(no podría inferir dónde está su salida System.err o un archivo, pero supongo que es el primero), que por defecto publica registros de registro del nivelLevel.INFO
. Tendrá que configurar este controlador, para publicar registros de registro de nivelLevel.FINER
y superior, para el resultado deseado.Recomendaría leer la guía de descripción general del registro de Java para comprender el diseño subyacente. La guía cubre la diferencia entre el concepto de Logger y Handler.
Editar el nivel de controlador
1. Usando el archivo de configuración
El archivo de propiedades java.util.logging (de forma predeterminada, este es el
logging.properties
archivo enJRE_HOME/lib
) se puede modificar para cambiar el nivel predeterminado de ConsoleHandler:2. Creación de controladores en tiempo de ejecución
Esto no se recomienda, ya que podría anular la configuración global. El uso de esto en toda su base de código resultará en una configuración de registrador posiblemente inmanejable.
fuente
Handler
.Logger.getGlobal().getParent().getHandlers()[0].setLevel(Level.FINER);
El porque
java.util.logging tiene un registrador raíz que tiene como valor predeterminado
Level.INFO
y un ConsoleHandler adjunto que también tiene como valor predeterminadoLevel.INFO
.FINE
es menor queINFO
, por lo que los mensajes finos no se muestran de forma predeterminada.Solución 1
Cree un registrador para toda su aplicación, por ejemplo, a partir del nombre o uso de su paquete
Logger.getGlobal()
, y conecte su propio ConsoleLogger a él. Luego, pídale al registrador raíz que se cierre (para evitar la salida duplicada de mensajes de nivel superior), o pídale a su registrador que no reenvíe registros a la raíz.Solucion 2
Alternativamente, puede bajar la barra del registrador raíz.
Puede configurarlos por código:
O con el archivo de configuración de registro, si lo está utilizando :
Al reducir el nivel global, puede comenzar a ver mensajes de las bibliotecas centrales, como algunos componentes Swing o JavaFX. En este caso, puede configurar un Filtro en el registrador raíz para filtrar los mensajes que no son de su programa.
fuente
¿Por qué mi registro de Java no funciona?
proporciona un archivo jar que le ayudará a averiguar por qué su inicio de sesión no funciona como se esperaba. Le brinda un volcado completo de qué registradores y controladores se han instalado y qué niveles están establecidos y en qué nivel en la jerarquía de registro.
fuente
POR QUÉ
Como lo mencionó @Sheepy, la razón por la que no funciona es que
java.util.logging.Logger
tiene un registrador raíz predeterminadoLevel.INFO
, y elConsoleHandler
adjunto a ese registrador raíz también predeterminadoLevel.INFO
. Por lo tanto, con el fin de ver elFINE
(,FINER
oFINEST
salida), es necesario establecer el valor predeterminado del registrador raíz y suConsoleHandler
aLevel.FINE
sigue como:El problema de su actualización (solución)
Como lo menciona @mins, los mensajes se imprimirán dos veces en la consola para
INFO
y arriba: primero por el registrador anónimo, luego por su padre, el registrador raíz, que también tiene unConsoleHandler
valorINFO
predeterminado. Para deshabilitar el registrador raíz, debe agregar esta línea de código:logger.setUseParentHandlers(false);
Hay otras formas de evitar que los registros sean procesados por el controlador de consola predeterminado del registrador raíz mencionado por @Sheepy, por ejemplo:
Pero
Logger.getLogger("").setLevel( Level.OFF );
no funcionará porque solo bloquea el mensaje que se pasa directamente al registrador raíz, no el mensaje proviene de un registrador secundario. Para ilustrar cómoLogger Hierarchy
funciona, dibujo el siguiente diagrama:public void setLevel(Level newLevel)
establezca el nivel de registro especificando qué niveles de mensajes registrará este registrador. Los niveles de mensaje inferiores a este valor se descartarán. El valor de nivel Level.OFF se puede utilizar para desactivar el registro. Si el nuevo nivel es nulo, significa que este nodo debe heredar su nivel de su antepasado más cercano con un valor de nivel específico (no nulo).fuente
Encontré mi problema real y no se mencionó en ninguna respuesta: algunas de mis pruebas unitarias estaban causando que el código de inicialización del registro se ejecutara varias veces dentro del mismo conjunto de pruebas, arruinando el registro en las pruebas posteriores.
fuente
Probé otras variantes, esto puede ser adecuado
fuente
Esta solución me parece mejor, con respecto a la mantenibilidad y el diseño para el cambio:
Cree el archivo de propiedades de registro incrustándolo en la carpeta del proyecto de recursos, que se incluirá en el archivo jar:
Cargue el archivo de propiedades desde el código:
fuente