Logging
In gvSIG the SLF4J library is used as a logging API.
The Simple Logging Facade SLF4J is a framework that is designed to abstract the underlying logging system. As Log4j is the most popular logging system in use, the framework's API is very similar to simply removing the direct dependence of this system. This framework is therefore an abstraction layer of the logging system and will allow us to change the underlying components without having to undertake major recoding of the application.
Features of SLF4J
- SLF4J is an abstraction layer independent of any actual logging system.
- Allows the end user to attach the desired implementation at deployment time.
- Allows gradual migration from Jakarta Commons Logging (JCL), because it has a JCL API wrapper in its own API.
- There is a parameterized logging system that reduces the overhead of assessing the message strings, especially when debug messages are enabled.
// Those lines produce the same results. The second one has parameters that reduce the overhead when debugging is disabled
LOG.debug("The new entry is "+entry+".");
LOG.debug("The new entry is {}.", entry);
- Support for Mapped Diagnostic Context (MDC), if the logging system operating under SLF4J supports it. At the moment only Log4j and logback do so.
- Logging systems may choose to implement the SLF4J interface directly as logback and SimpleLogger, or write SLF4J adapters for a given implementation as in the cases of Log4jLoggerAdapter and JDK14LoggerAdapter.
- Does not delegate to a specific class loading system (class loader) for delegating to a specific logging system, ie statically configured at compile time, only allowed to use one and only one logging system. Simply add the logging system API's jar to the CLASSPATH, together with slf4j-api.jar. This avoids the problems of class loading and memory loss suffered by Jakarta JCL.
- SLF4J also has an interface very similar to the JCL and Log4j APIs currently in use, so the implementation effort is significantly reduced.
- gvSIG continues to use the same logging toolkit (Log4j) so there will be practically no changes at run time.
- You gain in flexibility, robustness and efficiency through the ability to change the logging component without modifying the gvSIG source code, either for all versions of gvSIG or for specific versions.
- It's the standard that has been collected in OSGI projects because projects that are already using commons-logging can be adapted easily due to the popularity that this framework has gained.
Using SLF4J in gvSIG
gvSIG 2.0 is ready to work with SLF4J, using LOG4J as implementation, and can be used directly from any gvSIG extension.
To use SLF4J from a Java class just include the following statements:
1.- Import the necessary classes:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2.- Declare and initialize the Logger:
public class MyClass
{
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
...
3.- We use the Logger within the code of the class when we want to display a log message, depending on the type: error, warning, information, debug or trace:
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);
The following methods are provided to check the activation of messages for each level:
LOG.isErrorEnabled();
LOG.isWarnEnabled();
LOG.isInfoEnabled();
LOG.isDebugEnabled();
LOG.isTraceEnabled();
In addition, the messages can also be customized in SLF4J by inserting variables into the String of the log message, as in the following example:
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.");
}
}
This stops us from having to concatenate Strings, which reduces the cost of using the instructions for logging. This is because, although the log level that we are using is disabled (for example, debug), the method call will be made anyway, including the concatenation of strings to build the message, if any.
However, if the obtaining of any of the parameters to be passed to the message log proves costly, it is convenient to use the consultation methods to avoid such implementation. For example:
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());
}
}