JLog2 Lightweight Java Logger
 

Release Version 1.8.1

Introduction

 

The jlog2 software package is a lightweight logging application that allows you to log information relating to the operation of your software program. The package is written in Java under the J2ME platform and is compatible with both the CLDC and CDC versions. This package is used by the licas system, for example. The package provides functionality for logging general information or debugging information, to different sets of streams. It is based on creating channels to write to, and then allocating these to each logger that is used. A channel could be anything and so could include something like a text area GUI component, which would be written to instead of one of the standard outputs. There are also a small number of useful utility classes that perform some basic operations, not currently available under the restricted J2ME platform. The package is provided as a jar file that you include in your library and then use the relevant classes that you need.

 

Download

The software package can be downloaded from the sourceforge.net site. It comes with the jar file (only 12k in size), source code and user guide. It is very easy to use and the following sections outline some basic implementation details:




 

Initialise the Loggers

To initialise the logging, you make a call like:

LoggerFactory.setLoggerFactory(new CustomLoggerFactory());

And also store the logger.config file in a local config folder.

Create a Logger

To create a logger you need to declare a static object of type Logger in your class code and then initialise it through a static constructor. This logger will then be used by all instances of the class that are created. The logger needs to be initialised with the classname of the class it belongs to, for identification purposes. For example:

import org.jlog2.*;

public class YourClass
{
  /** The logger */
  private static Logger logger;

  static
  {
    // get the logger
    logger = LoggerHandler.getLogger(YourClass.class.getName());
    logger.setDebug(false);
  }
}

This would specify the logger for the YourClass class. To also output a debug trace for the specified file, you not only need to specify the configuration properties, but also set the debug variable for the logger to true. This means that you can debug only specific classes - that have the debug variable set to true. If no classes have the debug variable set then there will be no debug output trace. To log information, you then send the message to the LoggerHandler, for example:

LoggerHandler.logMessage(logger, LoggerHandler.INFO, "method", "message");

All logging should be done through a LoggerHandler call, which should also be used to choose the logging level.


Warning about Static Inheritance

Because the logger is static, there can be a problem if you declare the logger in a base class and then derive a number of classes from that. For example, if you write a class:

class YourBaseClass ()
{
  protected static Logger logger;
}

And then create two derived classes, in the following order:

class YourDerivedClass1 () extends YourBaseClass
{
  static
  {
    logger = LoggerHandler.getLogger(YourDerivedClass1.class.getName());
  }
}

class YourDerivedClass2 () extends YourBaseClass
{
  static
  {
    logger = LoggerHandler.getLogger(YourDerivedClass2.class.getName());
  }
}

If an error from 'YourDerivedClass1' is logged, it might be assigned the classname of 'YourDerivedClass2', because they have been assigned the same logger. This can be fixed by declaring a private logger in each derived class and not in the base class.

 


 

Configuration

The logger is easily configured through a logger.config configuration file that might look like:

log.channels = FO
debug.channels = f
log.file.path = licas.log
log.file.size = 100000
log.file.backup = 5
log.level = Info
debug.file.path = licas.debug
debug.file.size = 10000
debug.file.backup = 1
debug.level = info

 

These are all of the entries that you might use. There are separate entries for the logging streams and the debugging streams, starting with log. or debug. respectively. They configure the logger as follows:
  • The configuration allows the user to specify default channels to log to. These can be standard output (O), standard error (E), or a file (F). To log to these simply specify the combination of these letters.
  • The file.path properties specify the file name.
  • Each log file has a maximum size as specified by the file.size property. This is the maximum number of lines allowed in the log file. When this maximum value has been reached, the file is cleared of all entries and then filled with the new log information until the maximum value is reached again, etc.
  • You can also save earlier versions of the log file that would otherwise be overwritten when the maximum size is reached. The number of previous files that you keep is declared by the file.backup property.
  • Logging can be declared at different levels representing different levels of importance, using the .level entry. The levels available in order are: All, Info, Warn, Error, Severe, Message.

 

Note that the folders to read files from or write files to can now be set through the ConfigHandler. This should make the logger more compatible with an access-restricted mobile device.

 


 

Create Custom Loggers

You can also write your own logging channels by extending the LogChannel class and implementing the abstract methods. For example, you could create a swing TextArea component and choose to log to that instead of a file. You then need to add the new channel to the LoggerHandler as a default channel, to allow it to be included with every logger that is created. The documentation shows that this is easily achieved.






Contact Details

Author: Kieran Greer, Distributed Computing Systems.

For any queries about the software package, please contact the project administrator.
Email: DCS email.





Awards
The awards are listed on the main DCS site.