A medida que mis proyectos Java actuales crecen más y más, siento una necesidad cada vez mayor de insertar resultados de depuración en varios puntos de mi código.
Para habilitar o deshabilitar esta función de manera apropiada, dependiendo de la apertura o el cierre de las sesiones de prueba, generalmente pongo un private static final boolean DEBUG = false
al comienzo de las clases que mis pruebas están inspeccionando, y lo uso trivialmente de esta manera (por ejemplo):
public MyClass {
private static final boolean DEBUG = false;
... some code ...
public void myMethod(String s) {
if (DEBUG) {
System.out.println(s);
}
}
}
y similares.
Pero eso no me alegra, porque, por supuesto, funciona, pero podría haber demasiadas clases para establecer DEBUG en verdadero, si no está mirando solo un par de ellas.
Por el contrario, a mí (me gusta, creo que muchos otros) no me encantaría poner toda la aplicación en modo de depuración, ya que la cantidad de texto que se genera podría ser abrumadora.
Entonces, ¿hay una manera correcta de manejar arquitectónicamente tal situación o la forma más correcta es usar el miembro de la clase DEBUG?
Respuestas:
Desea mirar un marco de registro, y tal vez un marco de fachada de registro.
Existen múltiples marcos de registro, a menudo con funcionalidades superpuestas, tanto que con el tiempo muchos evolucionaron para depender de una API común, o se han utilizado a través de un marco de fachada para abstraer su uso y permitir que se intercambien en su lugar si es necesario.
Marcos
Algunos marcos de registro
Algunas fachadas de registro
Uso
Ejemplo básico
La mayoría de estos marcos te permitirían escribir algo del formulario (aquí usando
slf4j-api
ylogback-core
):Tenga en cuenta el uso de una clase actual para crear un registrador dedicado, que permitiría que SLF4J / LogBack formatee la salida e indique de dónde proviene el mensaje de registro.
Como se señala en el manual SLF4J , un patrón de uso típico en una clase suele ser:
Pero, de hecho, es aún más común declarar el registrador con el formulario:
Esto permite que el registrador también se use desde métodos estáticos, y se comparte entre todas las instancias de la clase. Es muy probable que esta sea su forma preferida. Sin embargo, como señaló Brendan Long en los comentarios, desea asegurarse de comprender las implicaciones y decidir en consecuencia (esto se aplica a todos los marcos de registro después de estos modismos).
Hay otras formas de crear instancias de registradores, por ejemplo, mediante el uso de un parámetro de cadena para crear un registrador con nombre:
Niveles de depuración
Los niveles de depuración varían de un marco a otro, pero los más comunes son (en orden de criticidad, de benignos a malos, y probablemente de muy comunes a, con suerte, muy raros):
TRACE
Información muy detallada. Debe escribirse solo en los registros. Se usa solo para rastrear el flujo del programa en los puntos de control.DEBUG
Información detallada. Debe escribirse solo en los registros.INFO
Eventos notables de tiempo de ejecución. Debe ser visible de inmediato en una consola, por lo tanto, use con moderación.WARNING
Runtime rarezas y errores recuperables.ERROR
Otros errores de tiempo de ejecución o condiciones inesperadas.FATAL
Errores graves que causan terminación prematura.Bloques y guardias
Ahora, supongamos que tiene una sección de código donde está a punto de escribir una serie de declaraciones de depuración. Esto podría afectar rápidamente su rendimiento, tanto por el impacto del registro en sí como por la generación de cualquier parámetro que pueda estar pasando al método de registro.
Para evitar este tipo de problema, a menudo desea escribir algo del formulario:
Si no hubiera utilizado esta protección antes de su bloque de sentencias de depuración, aunque los mensajes no se envíen (si, por ejemplo, su registrador está configurado actualmente para imprimir solo cosas por encima del
INFO
nivel), elheavyComputation()
método aún se habría ejecutado .Configuración
La configuración depende bastante de su marco de registro, pero ofrecen principalmente las mismas técnicas para esto:
También ofrecen principalmente las mismas capacidades:
Aquí hay un ejemplo común de una configuración declarativa, usando un
logback.xml
archivo.Como se mencionó, esto depende de su marco y puede haber otras alternativas (por ejemplo, LogBack también permite usar un script Groovy). El formato de configuración XML también puede variar de una implementación a otra.
Para obtener más ejemplos de configuración, consulte (entre otros) a:
Un poco de diversión histórica
Tenga en cuenta que Log4J está viendo una actualización importante en este momento, la transición de la versión 1.x de 2.x . Es posible que desee echar un vistazo a ambos para obtener más diversión histórica o confusión, y si elige Log4J, probablemente prefiera ir con la versión 2.x.
Vale la pena señalar, como Mike Partridge mencionó en los comentarios, que LogBack fue creado por un ex miembro del equipo Log4J. Que fue creado para abordar las deficiencias del marco de registro de Java. Y que la próxima versión principal de Log4J 2.x está integrando algunas características tomadas de LogBack.
Recomendación
En pocas palabras, manténgase desacoplado tanto como pueda, juegue con algunos y vea qué funciona mejor para usted. Al final es solo un marco de registro . Excepto si tiene una razón muy específica, además de la facilidad de uso y la preferencia personal, cualquiera de estos sería bastante correcto, por lo que no tiene sentido estar pendiente de él. La mayoría de ellos también se pueden extender a sus necesidades.
Aún así, si tuviera que elegir una combinación hoy, iría con LogBack + SLF4J. Pero si me hubieras preguntado unos años más tarde, te habría recomendado Log4J con Apache Commons Logging, así que vigila tus dependencias y evoluciona con ellas.
fuente
static
, ya que ahorra una pequeña cantidad de memoria, pero causa problemas en ciertos casos: slf4j.org/faq.html#declared_staticusar un marco de registro
la mayoría de las veces hay un método de fábrica estático
entonces puede generar su código de registro con diferentes niveles:
entonces habrá un único archivo donde puede definir qué mensajes para cada clase se deben escribir en la salida del registro (archivo o stderr)
fuente
Esto es exactamente para lo que están destinados los marcos de registro como log4j o el slf4j más nuevo. Le permiten controlar el registro con gran detalle y configurarlo incluso mientras la aplicación se está ejecutando.
fuente
Un marco de registro es definitivamente el camino a seguir. Sin embargo, también debe tener un buen conjunto de pruebas. Una buena cobertura de prueba a menudo puede eliminar la necesidad de generar resultados de depuración todos juntos.
fuente