The Java stack logs events through log4j.  The default log4j configuration defines a custom appender which causes the log4j-generated events to be forwarded to the log4c framework, allowing platform and Java logging events to be combined in a single log file.

Java stack logging no longer partially controlled from mpeenv.ini

Previously, the Java stack logging configuration was set to INFO in mpeenv.ini, and DEBUG level Java stack logging could be enabled by uncommenting the LOG.MPE.JAVA line.  This is no longer the case - the LOG.MPE.JAVA line in mpeenv.ini should not be changed. 

Instead, the default logging configuration is specified in log4j.properties (or an xml file - see below) in $OCAPROOT/bin/$OCAPTC/env and enables INFO level Java stack logging by default.  DEBUG level logging can be enabled by changing the root logger from INFO to DEBUG, and additional logger thresholds can be defined as needed.  For information on configuring log4j, see: http://logging.apache.org/log4j/1.2/manual.html

For example, to set the log4j.properties default logger verbosity to DEBUG, change the log4j.rootCategory entry in log4j.properties to:

  • log4j.rootCategory=DEBUG,DBG

The first value is the verbosity, the second value is the appender name (the log4j.properties configuration includes a 'DebugAppender' definition named 'DBG').

log4j and enhancements now a part of the public API

The 1.2 specification included a majority of log4j's APIs as well as additional features, including:

  • Ability to configure logging using DOMConfigurator or PropertyConfigurator
  • Logger methods supporting parameterized messages
  • Ability to associate a Logger with a Group programmatically
group feature simplifies configuration

The 'group' feature allows a number of Loggers to be associated with a single group programmatically.  Verbosity can then be defined in the configuration at the group level instead of the Logger level, allowing one group definition in the configuration to increase or decrease verbosity for a number of Loggers. 

For example, the ServiceContextImpl Logger and the delegate Loggers may all be associated programmatically with the 'serviceselection' group by creating the Logger using the Logger.getLogger(loggerName, groupName) method.  All of the Loggers associated with the 'serviceselection' group can then be set to DEBUG verbosity with one declaration in the XML or Properties-based configuration.

parameterized messages simplify code and and avoid string concatenation overhead

Logger methods supporting parameterized messages can be used to avoid both string concatenation and the need for if(log.isLEVELEnabled()) guards.  The first argument is the message parameter, which includes pairs of braces.  The following arguments replace the pairs of braces, in order, if the log message level passes the level threshold defined in the configuration.

For example: log.info("Received event {}", event) avoids the normal string concatenation that would be required when using log.info("received event " + event) and also avoids the need to wrap the concatenation in an if(log.isInfoEnabled()) guard.  The string is concatenated and a logging event constructed only if log is set to process INFO level logging events.

AsyncAppender supports moving the appender processing off of the caller thread

Logging overhead can affect performance.  If multiple cores and additional memory are available, some of the work done to facilitate logging can be moved off of the caller thread.  The AsyncAppender uses an additional thread and a size-configurable queue to move logging event processing by a target appender off of the caller thread and on to a dedicated thread.  An AsyncAppender definition can only be processed by DOMConfigurator.

On the caller thread, the Logger threshold is evaluated, the logging event is constructed, and the constructed logging event is placed on the AsyncAppender's queue.

If the queue is full, the AsyncAppender can be set to write a summary message to the log or switch in to blocking mode, where the target appender processes the event on the caller thread.  If the queue is not full, control returns to the caller as soon as the event is placed on the queue, and events are taken off of the queue by AsyncAppender's dedicated thread and the logging event is passed to the target appender for processing.

An AsyncAppender definition can be created in a DOM representation and passed to the DOMConfigurator programmatically, however, the RI can also use an XML file-based default logging configuration which defines an AsyncAppender.  In order to use an XML file-based configuration by default, define a log4j.xml file in $OCAPROOT/bin/$OCAPTC/env.  If you want to use a configuration file other than log4j.properties, add this entry to final.properties with the appropriate name:

  • OCAP.log4j.properties=/log4j.xml

If the OCAP.log4j.properties entry is not defined in final.properties (and an OCAP.log4j.properties entry is not defined in base.properties), a log4j.properties file will be used if it exists in $OCAPROOT/bin/$OCAPTC/env.  The path above with a leading slash implies a log4j.xml file exists at $OCAPROOT/bin/$OCAPTC/env, the same folder where the 'default' log4j.properties is created by the build process. NOTE: if overriding the default log4j.properties configuration, rename or delete any existing log4j.properties to avoid default accidental default configuration loading.

An example log4j.xml file containing an AsyncAppender definition is attached.

  • No labels