Sergio Morozov
MoMELog is a logging framework for J2ME architecture as log4J is for J2SE.
It resembles log4J very much. But, it has a different purpose, is build on other principals, and
is much more smaller and simple.
I will not discuss here in details all the principals and ideas that led to the development of this project. Please, read the Introduction To MoMELog. I will just remember the main of them. In my humble option, the aim of J2ME logging framework (at least now) should be it's use at development time as debugging tool. It should be as simple and extensible as possible. All logging events should be formatted using one method and presented to the developer via one mean (except, that some of them can be filtered out ;-)).
MoMELog logging framework is intended to be used at development time.
Of course, author doesn't prohibit it's use in final application (;-)), It is just not the aim of the project.
MoMELog doesn't support the notion of priority of logging events and doesn't maintain
the hierarchy of loggers. All logging events are formatted using one method and presented to the developer via one mean.
It is possible to suppress logging of group of loggers and/or vice versa allow logging only of group of loggers.
It is also possible to specify group of loggers that will issue logging only if user request contains
not-null error. Besides, MoMELog framework doesn't maintain a hierarchy of loggers,
it is recommended to specify structural categories. They are helpful in formatting
(e.g to use only last part of category) and/or suppressing/allowing logging or allowing only
logging events with not-null error for the group of loggers.
MoMELog logging framework consists of a small core and extensions that realize particular formatting method
or display logging information to the developer via particular mean.
MoMELog framework can be configured declaratively and/or programmatically.
Declarative configuration of the core of the framework and extensions is done by putting initialization file
in application's jar archive. It is a simple text properties file.
Programmatical configuration of the core of the framework can be done by invoking static methods
of Logger class. Programmatical configuration of extensions is realized by invoking instance methods
of particular extension.
Developers can set group of loggers, that are allowed and/or disallowed to log, group of loggers that are allowed
to log only events with error, type of Formatter intended to convert logging events to strings and
type of LogListener intended to make formatted logging information accessible to the developers.
Now MoMELog logging framework consists of three extensions:
PatternFormatter
is a Formatter that converts logging events to strings
based on conversion pattern. It's functionality and format of conversion pattern
resemble very much that of log4J framework. It can be configured declaratively and/or programmatically.
It is preset with default pattern and doesn't require configuration.
See PatternFormatter Guide for details.
LogCanvas
is a LogListener intended to display logging events on device's
or emulator's screen. It is fully functional Canvas. It has very simple and convenient GUI.
Users can scroll one line or page down or up and go to the beginning or to the end of text, toggle
fullscreen mode and reset buffer by pressing one key. Scrollbar's cursor has
different color at the edge positions (top and bottom) from that at the middle, this way, indicating first and
last line. It is fully customizable. It is possible to completely configure it's view. Key events are processed
in separate thread, started, when canvas is shown and stopped on hide.
This eliminates conflicts with callbacks processing thread. It can be configured declaratively
and/or programmatically. Like any other Displayable it requires some programming work to be done
to make use of it. See LogCanvas Guide for details.
LogFile
is a LogListener intended to collect formatted logging events
in the destination file. It can be used only on devices or emulators that support FileConnection API.
It is fully configurable. Users can specify path, character encoding, header and footer lines of destination file
and prefix and suffix of each logging line. It can be configured declaratively and/or programmatically.
It provides meaningful default values for all properties and doesn't require configuration.
See LogFile Guide for details.
Some of the extensions (i.e LogCanvas) require some programming work to be done to make use of them.
As MoMELog is intended to be used at development time and by developer it is not considered
as big problem.
MoMELog logging framework is very simple. It consists of three parts:
Logger, Formatter,
LogListener.
Fig-1. MoMELog Framework.
Logger is the main part of MoMELog framework. It generates logging events
on user request and directs them to the configured LogListener. LogListener converts
these events to formatted strings using configured Formatter and makes obtained strings available
to the user (e.g. shows on screen, puts in RMS, sends via http/https, appends to a file or any other way).
Loggers are distinguished by categories, that are the case-sensitive identification strings.
MoMELog doesn't maintain the hierarchy of loggers. All loggers are even.
It is possible to suppress logging of group of loggers and/or allow logging of only group of loggers, by specifying
disallowed categories and allowed categories lists respectively. They are a comma separated lists
of patterns. Logger can only log it's events, if it's category matches one of the patterns in allowed categories
list and not in disallowed categories list. If any of the lists is empty, it is not considered.
It is recommended to use structural categories. This can be very helpful in formatting logging events and gives better
possibilities to suppress or allow logging of a group of loggers. It is also possible to specify group of
loggers that will generate logging event only if user request contains not-null error.
This feature is realized by onlywitherror categories list, that is also the list of patterns.
Pattern can contain any text and only one type of special character - asterisk (*).
Asterisk, like in file regular expression, designates any number of any characters.
Of course, pattern can contain zero or more asterisks.
For example pattern "somepackage.*Screen", specifies categories that start with
"somepackage." and ends with "Screen".
MoMELog framework doesn't support the notion of priority. All logging events are even.
The feature of filtering out logging events based on their properties (except not-null error)
can be built in a particular LogListener implementation and is not realized by the core of the framework.
In MoMELog framework logging events have the following properties:
Throwable supplied by the user.Logger class loading time. It, of course, can be changed later.
MoMELog framework can be configured declaratively and/or programmatically.
Declarative configuration of the core of the framework and extensions is done by putting initialization file
.momelog.txt (don't omit preceding dot ;-)) in application's jar archive. This is a simple
text properties file, where lines are separated by new-line characters and empty lines and lines
that start with hash (#) (preceding spaces are allowed) are ignored.
The core of the framework can be also configured programmatically by using static methods of
Logger class.
Programmatical configuration of LogListener and/or
Formatter can be done by using instance methods of respective implementation. Declarative configuration
occurs at Logger class loading time and
programmatical one, of course, overrides it. See Configuration chapter for details.
The core framework provides means to set the type of LogListener used for presenting logging
to the developer, type of Formatter used for converting logging events to strings and
allowed categories, disallowed categories and onlywitherror categories lists.
MoMELog is preconfigured with PatternFormatter, no LogListener and
empty allowed categories, disallowed categories and onlywitherror categories lists.
Developer need to supply the type of LogListener to use declaratively (recommended) or programmatically.
In other case no logging events will be generated.
The core of the MoMELog framework consists of 5 classes.
Logger
is the main class of MoMELog logging framework.
It is the class that developers will mostly deal with. It provides static methods for general framework configuration
and obtaining Logger instances. It also provides instance methods to request logging.
Formatter
is an abstract base class, that every Formatter needs
to extend. It provides three methods intended to convert logging events to strings or any other objects.
LogListener
is an interface, that every LogListener
needs to implement. It provides the only method
onLog(LogEvent event)
called on every logging event.
LogEvent
is a bean, that represents information about the logging event.
Configurable
is an interface, that every class interesting
to be configured from character sequence needs to implement. It contains the only method
configure(char[] lines, int offset, int length),
where actual configuration should be realized.
MoMELog also consists of three extensions:
PatternFormatter
is Formatter implementation
that converts logging events to strings
based on conversion pattern. It's functionality and format of conversion pattern
resemble very much that of log4J framework. It can be configured declaratively and/or programmatically.
It is preset with default pattern and doesn't require configuration.
See PatternFormatter Guide for details.
LogCanvas
is LogListener implementation
intended to display logging events on device's
or emulator's screen. It is fully functional Canvas. It has very simple and convenient GUI.
Users can scroll one line or page down or up and go to the beginning or to the end of text, toggle
fullscreen mode and reset buffer by pressing one key. Scrollbar's cursor has
different color at the edge positions (top and bottom) from that at the middle, this way, indicating first and
last line. It is fully customizable. It is possible to completely configure it's view. Key events are processed
in separate thread, started, when canvas is shown and stopped on hide.
This eliminates conflicts with callbacks processing thread. It can be configured declaratively
and/or programmatically. Like any other Displayable it requires some programming work to be done
to make use of it. See LogCanvas Guide for details.
LogFile
is LogListener implementation
intended to collect formatted logging events
in the destination file. It can be used only on devices or emulators that support FileConnection API.
It is fully configurable. Users can specify path, character encoding, header and footer lines of destination file
and prefix and suffix of each logging line. It can be configured declaratively and/or programmatically.
It provides meaningful default values for all properties and doesn't require configuration.
See LogFile Guide for details.
Usage of MoMELog framework is pretty simple. It is very similar to that of log4J framework.
As mentioned in Description chapter, MoMELog doesn't
support the notion of priority of logging. That's why, there are only two methods
(defined in Logger class) intended
to log messages and/or errors log(String message)
and log( String message, Throwable error).
First of them logs just the specified message and last - message and error. Any of the parameters can be
null, of course.
Like in log4J framework, the above methods should be called on
Logger instance. There are three static factory methods defined in
Logger class
Logger.getLogger(String category),
Logger.getLogger(Class clazz) and
Logger.getLogger() intended to return
Logger instance.
The first method returns Logger instance of specified category.
In the second case category is the name of the given class
(like from Class.getName() method). The last convenient
Logger.getLogger() method returns
Logger instance of default category, that is a slash (/).
Besides, the same Logger instance is returned for
the same category (case is significant), it is recommended to save reference
to Logger instance in static variable.
For example, class Apollo is using MoMELog for logging.
public class Apollo
{
// obtaining logger of Apollo category.
private static final Logger log = Logger.getLogger( Apollo.class);
...
public method launch()
{
// logging a message.
log.log( "launch started.");
...
try
{
...
// logging a message.
log.log( "launch completed.");
} catch( Throwable err)
{
// logging a message and error.
log.log( "Huston we have a problem", err);
...
}
}
...
}
MoMELog is a simple logging framework. It does not require complex configuration. In general,
it can be completely configured declaratively. But, some
LogListener implementations can require
additional programming work (e.g. LogCanvas).
MoMELog framework can be configured declaratively and/or programmatically. Declarative configuration
is done by putting initialization file .momelog.txt (don't omit preceding dot ;-)) in the application's
jar archive. This is a text properties file.
MoMELog framework declarative configuration occurs at
Logger class loading time.
This gives developers possibility to override it programmatically.
MoMELog distinguishes general framework, formatter and
listener configurations.
General framework configuration includes setting the type of Formatter to use for converting
logging events to strings or any other objects, the type of LogListener to use for processing
logging events (e.g. displaying them on a screen, saving in RMS, sending via http/https or
appending to a file) and allowed categories, disallowed categories and
onlywitherror categories lists to control logging of groups of loggers.
MoMELog is not preset with some type of LogListener.
Developer needs to specify it declaratively (recommended) or programmatically.
MoMELog framework is preconfigured to use
PatternFormatter for converting logging events
to strings. It is also preset with empty allowed categories,
and onlywitherror categories lists (i.e. all loggers are allowed to log).
Formatter and listener configurations consist of setting Formatter and LogListener
instances respectively. These configurations depend on particular
Formatter or
LogListener implementation used.
See respective Formatter or LogListener documentation for details.
As mentioned above, declarative configuration is done by putting initialization file .momelog.txt
(don't omit preceding dot) in application's jar archive.
This file is the text properties file. It's format is very simple. Lines must be terminated by
new-line character ('\n'). All empty lines and lines, that consist only of spaces
are ignored. All lines that start with pound sign (#) (preceding spaces are allowed) are considered as comments and ignored too. All other lines are considered as configuration lines and parsed.
The format of configuration line is
[S*]name[S*]=[S*]value[S*]
S is a space (or horizontal tab).name is the name of configuration property.value is the value of configuration property.Spaces around names are always ignored. Significance of spaces around values depends on particular property.
If line is of invalid format, property name is unknown or property has invalid value, the warning message is printed to standard error output and offending line is ignored.
MoMELog supports following general configuration properties.
Spaces around all general configuration properties values are ignored. If any property is specified more than one time,
the last prevails.
|
Property Name |
Description |
Default Value |
|
"listener" |
Name of Note: If specified class can't be found, instantiated or doesn't implement
Since version 1.0 |
None |
|
"formatter" |
Name of Note: If specified class can't be found, instantiated or doesn't extend
By default, Since version 1.0 |
|
|
"allowedcategories" |
Comma separated list of patterns.
Pattern can contain any text and only one type of special character - asterisk ( Since version 1.0 |
empty string ("")
|
|
"disallowedcategories" |
Comma separated list of patterns.
Pattern can contain any text and only one type of special character - asterisk ( Since version 1.0 |
empty string ("")
|
|
"onlywitherrorcategories" |
Comma separated list of patterns.
Pattern can contain any text and only one type of special character - asterisk ( Since version 1.0 |
empty string ("")
|
For example following initialization file snippet configures MoMELog to use
PatternFormatter for converting
logging events to strings,
LogFile for making logging events accessible,
disallows logging of logger of the "NotInterestingClass" category and allows only
error logging of loggers with the categories that start with "somelibrary.".
# configuring MoMELog to use PatternFormatter # this is redundant as MoMELog is preconfigured with it formatter = momelog.formatter.PatternFormatter # configuring MoMELog to use LogFile listener = momelog.listener.LogFile # disallows logging of NotInterestingClass logger disallowedcategories = NotInterestingClass # allows only error logging of somelibrary onlywitherrorcategories = somelibrary.*
LogListener can be configured declaratively from initialization file by specifying it's specific properties.
All names of listener configuration properties must start with "listener." prefix.
After this prefix removal, they are directed to the specific
Loglistener implementation instance.
See particular listener documentation for the list of supported properties.
MoMELog framework now contains LogCanvas
and LogFile
LogListener implementations.
See LogCanvas Guide or
LogFile Guide for the list of supported properties.
Formatter can be configured declaratively from initialization file by specifying it's specific properties.
All names of formatter configuration properties must start with "formatter." prefix.
After this prefix removal, they are directed to the specific
Formatter implementation instance.
See particular formatter documentation for the list of supported properties.
MoMELog framework now contains only
PatternFormatter
formatter implementation.
See PatternFormatter Guide for the list of supported properties.
As mentioned above, MoMELog framework can be configured declaratively and/or programmatically.
Besides, declarative configuration is the preferred one, developers can configure framework programmatically.
Also some
Formatter or
LogListener implementations can require some programming work
to be performed. As MoMELog logging framework is intended to be used at development time and by developers,
it is not considered as big problem. Programmatical configuration, of course, overrides declarative.
All programmatical general framework configuration can be performed by using static methods of
Logger class.
Instance of LogListener implementation
to be used for making logging information accessible to the developer can be set by using
Logger.setLogListener(LogListener listener)
static method. Invoking this method with null unsets LogListener
(or sets it to null).
MoMELog is preset with no LogListener
implementation. Developers need to set it or no logging events will be generated. Of course, it is more convenient
to do this declaratively. Configured LogListener can be obtained by calling
Logger.getLogListener()
static method.
Instance of Formatter implementation
to be used for converting logging events to strings or any other objects can be set by using
Logger.setFormatter(Formatter formatter)
static method. This method throws NullPointerException on null parameter.
MoMELog is preset with
PatternFormatter
initialized with default pattern. Configured Formatter can be obtained by calling
Logger.getFormatter()
static method.
To control logging of different loggers MoMELog defines notions of allowed categories,
disallowed categories and onlywitherror categories. They are a comma separated lists of patterns.
Logger instance can only log, if it's category matches any pattern in allowed list
and none in disallowed. If category of the Logger instance matches any of the patterns in
onlywitherror list, it is allowed only to log events with errors.
If any list is set to an empty string, it is not considered. Allowed categories, disallowed categories
and onlywitherror categories lists can be set by invoking
Logger.setAllowedCategories(String),
Logger.setDisallowedCategories(String)
and Logger.setOnlyWithErrorCategories(String)
static methods respectively. Allowed categories, disallowed categories
and onlywitherror categories lists can be obtained by calling
Logger.getAllowedCategories(),
Logger.getDisallowedCategories() and
Logger.getOnlyWithErrorCategories()
static methods respectively.
As mentioned in the Description chapter logging event has a property of timestamp,
that is the long integer indicating time of issuing of this logging event. Actually, it is the number of milliseconds from some base time point till logging event generation. By default, this base time point is set to
Logger class loading time.
By calling
Logger.resetBaseTime()
static method base time point can be set to now.
All of the above static methods can be called at any time. In typical usage, of course, all these methods except
Logger.resetBaseTime()
are called at the start of the application (e.g. in MIDlet.startApp() method).
For example in MIDlet SomeMIDlet.
...
protected void startApp()
{
if( !started)
{
// if MoMELog is configured to use LogCanvas declaratively it can be obtained by
//logScr = (LogCanvas) Logger.getLogListener();
// if MoMELog is not configured to use LogCanvas declaratively it should be instantiated.
logScr = new LogCanvas();
// ordinary Canvas configuration.
logScr.addCommand( BACK);
logScr.setCommandListener( this);
// LogCanvas specific configuration.
logScr.setFont( Font.getFont( Font.MONOSPACE,FONT.PLAIN,Font.SMALL);
// setting our pattern of PatternFormatter.
// as MoMELog is preset with PatternFormatter
// we don't need to instantiate it.
((PatternFormatter) Logger.getFormatter()).setPattern( "%.5C>%m %e at %t [%h]");
// disallowing logging of NotInterestingClass class.
Logger.setDisallowedCategories( "NotInterestingClass");
// configuring to receive only error logging from somelibrary
Logger.setOnlyWithErrorCategories( "somelibrary.*");
// if MoMELog is configured to use LogCanvas it is redundant
Logger.setLogListener( logScr);
...
started = true;
}
...
}
LogListener implementation
used for processing logging events can also be configured programmatically.
See particular LogListener documentation for details.
All LogListener implementations should provide
meaningful default values for their properties to minimize necessary configuration.
Taking into consideration restrictions and specificity of J2ME architecture and functionality of
some LogListeners, this is not always possible.
Some LogListeners require programming work to be performed to make use of them.
As MoMELog framework is intended to be used at development time, it is not considered as big problem.
MoMELog framework consists now of two
LogListener implementations:
LogCanvas - listener
intended to display formatted logging events on device's or emulator's screen. It extends GameCanvas
class and like any canvas requires some programming work to be performed.
See LogCanvas Guide for details.
LogFile - listener
intended to collect formatted logging events in the destination file. It can be used only on
devices or emulators that support FileConnection API. It provides meaningful default values
for all properties and doesn't require configuration.
See LogFile Guide for details.
Formatter implementation
used for converting logging events to strings can also be configured programmatically.
See particular Formatter documentation for details.
All Formatter implementations should provide
meaningful default values for their properties to minimize necessary configuration.
MoMELog framework consists now of only one formatter -
PatternFormatter - formatter
that converts logging events to strings based on configuration pattern. It's functionality and
pattern's format resemble very much that of log4J framework.
It provides meaningful default values for all properties and doesn't require configuration.
See PatternFormatter Guide for details.
Sergio Morozov. 2007