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