Logging
En gvSIG se emplea la librería SLF4J como API de logging a emplear.
SLF4J Simple Logging Facade o "Fachada de Registro Simple" es un framework que se ha creado para abstraer el sistema de registro que hay por debajo. Como el sistema de registro más popular usado es Log4j, el API del framework es muy similar para simplificar al máximo eliminar la dependencia directa de este sistema. Este framework por tanto es una capa de abstracción del sistema de registro, y nos va a permitir cambiar el componente de registro que lleve por debajo sin necesidad de un gran esfuerzo de recodificación de la aplicación.
Características de SLF4J
- SLF4J es una capa de abstracción independiente cualquier sistema de registro "logging" concreto.
- Permite al usuario final acoplar la implementación deseada en tiempo de despliegue.
- Permite una migración gradual a partir de Jakarta Commons Logging ( JCL ), ya que dispone de un wrapper del API de JCL sobre su propio API.
- Dispone de un sistema de registro parametrizado que reduce el overhead de evaluar los strings de los mensajes, sobre todo cuando no están habilitados los mensajes de debug.
// Those lines produce the same results. The second one has parameters that reduce the overhead when debuggin is disabled
LOG.debug("The new entry is "+entry+".");
LOG.debug("The new entry is {}.", entry);
- Dispone de soporte para Mapped Diagnostic Context ( MDC ), si el sistema de registro que funciona bajo SLF4J lo soporta. Por el momento sólo lo hacen Log4j y logback .
- Los sistemas de logging pueden escoger entre implementar el interfaz de SLF4J directamente como logback y SimpleLogger ó escribir adpatadores SLF4J para una implementación dada como en los casos de Log4jLoggerAdapter y JDK14LoggerAdapter .
- No delega en un sistema de carga de clases específico (class loader) para delegar en un sistema de registro específico, es decir, se configura estáticamente en tiempo de compilación, sólo se permite usar uno y sólo un sistema de registro logging . Simplemente se añade al CLASSPATH el jar del API del sistema de logging junto con slf4j-api.jar. Esto evita los problemas de carga de clases y pérdidas de memoria sufridos por Jakarta JCL .
- SLF4J tiene también una interfaz muy próxima a JCL y Log4j API actualmente en uso, por tanto el esfuerzo de implementación se reduce significativamente.
- gvSIG continúa utilizando el mismo toolkit de logging ( Log4j ) por tanto, prácticamente no existen cambios en tiempo de ejecución.
- Se gana en flexibilidad, robustez y eficiencia, mediante la posibilidad de cambiar el componente de logging, ya sea para todas las versiones de gvSIG o alternativamente para versiones concretas sin modificar el código fuente de gvSIG.
- Es el standard que se ha recogido en los proyectos OSGI , debido a que puede adaptar proyectos que ya usan commons-logging con facilidad, debido a la popularidad adquirida de este framework estudiado anteriormente.
Cómo usar SLF4J en gvSIG
gvSIG 2.0 ya está preparado para trabajar con SLF4J, usando LOG4J como implementación, por lo que podemos usarlo directamente desde cualquier extensión de gvSIG.
Para usar SLF4J desde una clase Java basta con incluir las siguientes sentencias:
1.- Importar las clases necesarias
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2.- Declaramos e inicializamos el Logger.
public class MyClass
{
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
...
3.- Usamos el Logger dentro del código de la clase, cuando queramos mostrar un mensaje de log, dependiendo del tipo: error, alerta, información, depuración o traza:
LOG.warn(String message);
LOG.warn(String message,Object arg1);
LOG.warn(String message,Object[] arg1);
LOG.warn(String message, Throwable arg1);
LOG.info(String message);
LOG.info(String message,Object arg1);
LOG.info(String message,Object[] arg1);
LOG.info(String message, Throwable arg1);
LOG.error(String message);
LOG.error(String message,Object arg1);
LOG.error(String message,Object[] arg1);
LOG.error(String message, Throwable arg1);
LOG.debug(String message);
LOG.debug(String message,Object arg1);
LOG.debug(String message,Object[] arg1);
LOG.debug(String message, Throwable arg1);
LOG.trace(String message);
LOG.trace(String message,Object arg1);
LOG.trace(String message,Object[] arg1);
LOG.trace(String message, Throwable arg1);
Los siguientes métodos se proporcionan para consultar la activación de los mensajes por nivel:
LOG.isErrorEnabled();
LOG.isWarnEnabled();
LOG.isInfoEnabled();
LOG.isDebugEnabled();
LOG.isTraceEnabled();
En SLF4J tenemos la capacidad adicional de parametrizar los mensajes, insertando variables dentro de la cadena String del mensaje de registro, como en el siguiente ejemplo:
private Integer temperature;
public void setTemperature(Integer temperature) {
LOG.debug("Setting temperature to {}. Old temperature was {}.", temperature, this.temperature);
this.temperature = temperature;
if(temperature.intValue() > 50) {
LOG.info("Temperature has risen above 50 degrees.");
}
}
Esto evita que tengamos que ir concatenando Strings, lo cuál reduce el coste del uso de las instrucciones de logging. Esto es debido a que, aunque el nivel de log que estemos usando esté desactivado (por ejemplo, el de debug), la invocación al método se hará de todas formas, incluyendo la concatenación de Strings para construir el mensaje, si la hubiera.
De todas formas, si la obtención de alguno de los parámetros que vamos a pasar al mensaje de log fuera costosa, es conveniente emplear los métodos de consulta para evitar dicha ejecución. Por ejemplo:
private Integer temperature;
public void setTemperature(Integer temperature) {
LOG.debug("Setting temperature to {}. Old temperature was {}.", temperature, this.temperature);
this.temperature = temperature;
addToTemperatureLog(temperature);
if (LOG.isDebugEnabled()) {
LOG.debug("The current average temperature is {} Celsius", calculateAverageTemperature());
}
}