The Players
The most basic form of logging is to 'log' a message on some output device or destination, such as a file. In log4s, an EsLoggingEvent is the entity which is logged. In the figure below, an EsLoggingEvent containing the message 'Hi, Mom' is sent to an EsLogger which then asks its EsAppender to log the message.
The logger is simply a link between an event and one or more appenders. The appender determines where an event is logged and assesses whether it should be logged at all.
Logging Events
A logging event is an instance of the class EsLoggingEvent. Every logging event must have a message, a creation timeStamp, and a level. Optionally, it may also have the name of the class and method that created it and a wildcard object that can be anything at all.
The creation timeStamp by default is in the time zone of the operating system. You can force the timeStamp to be recorded in a different time zone by using the timeZoneOverride parameter (described
below) in the ini file.
The message instance variable is generally a string, but it can also be a block that will later resolve to a string when and if the logging event gets logged. For example:
EsLogManager logInfo: [ ‘Hi there %1’ bindWith: aUserid ]
Loggers
A logger is an instance of EsLogger that has a case-sensitive name and has one or more Appenders. The log4s framework always has one rootLogger named 'root'.
Appenders
An appender is best thought of as an output destination, and is an instance of the class EsAppender or one of its sub classes. Currently there are Appenders for files, the console, sockets, and the Transcript.
A logger can have multiple Appenders. The diagram above shows a logger that has an EsConsoleAppender named ‘consoleAppender’ and an EsFileAppender named ‘fileAppender.’
There is a special appender called an EsAsyncAppender which is not truly an appender, but rather the holder of a collection of appenders to which it writes asynchronously. The appenders described previously do their logging work synchronously; the logging event must be successfully written before the rest of the application can continue. This can be a problem where, for instance, file I/O is too slow for the application.
An asynchronous appender allows logging to occur in the background and the current application to continue immediately. An asynchronous appender is attached to a logger, and then other appenders are attached to it. Logging events sent to an asynchronous appender are put on a logging event queue and control is returned immediately to the application. A background task in the asynchronous appender retrieves logging events from the logging event queue and forwards them to the appenders attached to the asynchronous appender.
The example below shows an asynchronous appender named ‘asyncVastAppender’ attached to the root logger. The asyncAppender has an EsConsoleAppender named ‘consoleAppender,’ an EsFileAppender named ‘asyncFileAppender,’ and an EsRollingFileAppender named ‘asyncRollingFileAppender’ attached to it.
Controllers of What Gets Logged
It is just as uninformative to get too many events in a log as too little. Levels and filters allow a user to specify what is of interest by characterizing the severity of the event, by noting the context in which an event is of interest, or by evaluating an event against some criterion.
Level
The concept of levels is central to log4s. A logging event will be logged by an appender if the level of the logging event is greater than or equal to the level of the appender. Both EsLoggingEvents and EsAppenders have levels. Log4s has seven predefined levels which are implemented as EsLevel class variables.
| | |
ALL | SmallInteger smallest | ini file only |
DEBUG | 10000 | |
INFO | 20000 | |
WARN | 30000 | |
ERROR | 40000 | |
FATAL | 50000 | |
OFF | SmallInteger largest | ini file only |
Two examples illustrate conditions under which an event is or is not logged.
The logging event in the diagram above will be logged because the level of the logging event is WARN and the appender with level INFO will log logging events with levels from INFO through FATAL
The logging event in the diagram above will not be logged because the level of the logging event is WARN and the appender with level ERROR will only log logging events with levels ERROR and FATAL.
Filter
Filters allow even more control over what gets logged. A filter is attached to an appender; an appender can have multiple filters. Level checks precede filter checks. A logging event must pass all the filters attached to an appender in order to appear in a log.
Appenders store their filters in an OrderedCollection, which allows filters to be 'chained'. Denial by any of the filters in the chain excludes the logging event from the log. Note that the filters are evaluated in the order in which they were added to the filter instance variable.
The Log4s framework has predefined filters that allow events whose properties meet some criteria such as matching a class name, a string in the logging event message, a Level, or a range of Levels.
The logging event in the diagram above passes the level check of the appender, but it will not be logged because it does not pass the stringMatchFilter which requires that the message of the logging event ('Hi, Mom') includes the string 'Fred'. Once again, notice that the event must satisfy both the level and the filter to make it into the log.
Return Value
Filters return Accept, Deny, or Neutral after evaluating the logging event.
Predefined Filters
Log4s has these predefined filters:
• ClassNameFilter - filter out logging events whose className does not match. The comparison is not case sensitive.
• LevelMatchFilter - filter out logging events whose level falls below a single level.
• LevelRangeFilter - allow through logging events whose level lies within a range of levels.
• StringMatchFilter - filter out logging events whose message does not match a string. The comparison can be made case insensitive.
Controlling Acceptance of EsLoggingEvent
The filter normally returns an Accept when the logging event matches the filter criterion. However, the user can specify an Accept for logging events which differ from the filter criterion. Accepting logging events which match or differ from the filter criteria is controlled by an instance variable acceptOnMatch, which defaults to true.
Each filter has an alternate instance creation method which instantiates a filter that accepts logging events which differ from the criterion. For instance:
EsLevelMatchFilter
name: 'aLevelMatchFilter'
levelToMatch: (EsLevel Warn)
acceptOnMatch: false