Laboratorio de Programación > Material de estudio > Apuntes > Trazas de ejecución
El nivel de detalle de las trazas de ejecución interesa que sea ajustable según las circunstancias: dinámicamente.
Las trazas serán de poco detalle cuando empezamos a buscar; pero iremos aumentando el detalle según vayamos acorralando el error.
No es ninguna novedad que los programadores "trufen" el código de sentencias System.err.println para dejar traza de por dónde vamos pasando y en valor que van tomando las variables. Lo malo de esta aproximación es que las sentencias de escritura hay que anularlas cuando el sistema se pone en producción, bien comentándolas, bien eliminándolas, bien armando algún mecanismo de control dinámico del nivel de detalle deseado (así, nivel cero significa que no hay traza alguna, lo que es típico de producción).
Java incluye un paquete que permite automatizar la tarea de activar y desactivar trazas con diferente nivel de detalle.
Está inspirado en el paquete java.util.logging de la librería de Java (que se describe al final); pero adaptado a la asignatura.
Es necesario incluir el paquete:
import log.Logger;
Para trazar necesitamos un logger:
Logger LOGGER= Logger.getLogger("NOMBRE")
Decidir exactamente el nivel de granularidad depende de cada caso.
Podemos empezar con un logger por paquete:
private static final Logger LOGGER= Logger.getLogger("paquete")
Si el paquete es grande (muchas clases)
puede ser interesante tener un logger para cada clase
o para algunas clases:
private static final Logger LOGGER= Logger.getLogger("paquete.clase")
Si una clase es muy grande (muchos métodos)
puede ser interesante tener in logger para cada método
o para algunos métodos:
private static final Logger LOGGER= Logger.getLogger("paquete.clase.metodo")
En los ejemplos de estos apuntes usaremos un logger por clase.
Los nombres forman una jerarquía o "árbol genealógico" que nos permitirá fijar el nivel de detalle de traza de familias enteras, pues el nivel que fijemos para un logger será el que usen todos sus "descendientes", salvo indicación expresa.
Así podremos dar reglas para todos los paquetes, reglas que refinaremos en algunos paquetes, podremos refinar más por clases e incluso por métodos. Según haga falta.
| OFF | No se genera traza alguna. |
|---|---|
| SEVERE | Se usa para trazar errores catastróficos, que son aquellos de los que no hay recuperación posible, provocando la terminación del programa. La traza recoge el fallo causante de la detención. |
| WARNING | Se usa para trazar errores peligrosos, para los que hay previsto un mecanismo de supervivencia. |
| INFO | Trazas normales: para ir viendo lo que pasa. |
| CONFIG | Se usan típicamente al arrancar un programa para trazar la configuración inicial, que frecuentemente se lee de alguna parte. |
| FINE | Información de detalle, típicamente útil para localizar errores (depuración). |
| FINER | Información de más detalle, típicamente útil para localizar errores (depuración). |
| FINEST | Información de máximo detalle, típicamente útil para localizar errores (depuración). |
| ALL | Se traza todo, a cualquier nivel. |
Los siguientes ejemplos de uso deberían ser obvios:
LOGGER.log(Logger.WARNING, "mensaje"); LOGGER.severe("mensaje"); LOGGER.warning("mensaje"); LOGGER.info("mensaje"); LOGGER.config("mensaje"); LOGGER.fine("mensaje"); LOGGER.finer("mensaje"); LOGGER.finest("mensaje");
La más sencilla consiste en asociar el texto de la
excepción a la traza:
LOGGER.warning("mensaje " + e);
También se puede pasar como tercer argumento a log:
LOGGER.log(Logger.WARNING, "mensaje ", e);
Se usa siempre el fichero
$HOME/logger.java
El directorio $HOME depende del sistema operativo en el que trabajemos; pero si el paquete no encuentra el fichero, indica por medio de un mensaje en consola qué es lo que estaba buscando, de forma que podamos llevar el fichero a su sitio.
$ java Diccionario
no se encuentra: C:\Documents and Settings\pepe\java.logger
Y cuando lee el fichero, indica qué es lo que está leyendo:
$ java Diccionario
java.logger <- C:\Documents and Settings\pepe\java.logger
El fichero java.logger indica varias cosas.
Si un Logger tiene por nombre una serie de palabras separadas por puntos
a.b.c.d
se buscará sucesivamente alguna entrada en java.logger que diga
Para probar, debe organizar la jerarquía de directorios paralela a la jerarquía de paquetes. Algo así
C:\java\lprg\2006-01-31\Diccionario.java
C:\java\lprg\2006-01-31\log\Logger.java
Para ejecutar el programa ejemplo puede interesarle usar este diccionario inicial de palabras.
Se adjunta el resultado de ejecutar con diferente nivel de traza:
El paquete java.util.logging es similar a log.Logger pero permite hacer muchas más cosas que las que se describen en esta nota. Para una referencia completa, se remite al lector a
Java Logging Overview
Thinking in Java, el libro de Bruce Eckel, incluye un capítulo dedicado a las trazas con extenso detalle.