|
GreyLog
is a fully configurable, high performance logging framework, which contains particular optimisations to support 8-bit charsets (ie. the vast majority) and single-threaded mode.
It consists of the
com.grey.logging
Java package.
GreyLog differs from
Log4j12, JUL (java.util.logging)
and other logging frameworks, in that its loggers really are logfile streams, and not merely formatting handlers that cascade into a single actual logger.
This means that care has to be taken when instantiating GreyLog loggers via
external interfaces such as
SLF4J
or
JCL (Apache Commons Logging).
SLF4J and JCL are biased towards Log4j12 and JUL, and developers typically expect to call
org.slf4j.LoggerFactory.getLogger()
or
org.apache.commons.logging.LogFactory.getLog()
in every module, using a different name each time, without actually creating multiple I/O streams.
In the case of GreyLog, this would result in multiple logfile streams which is probably not what you intended, so the required loggers need to be created in one place and then made available (as is the case with the
Dispatcher.logger
field provided by NAF).
GreyLog is part of the
NAF
suite, but it has no dependency on NAF's reactor core and is suitable for use by non-NAF applications,
whether invoked directly or via facades like SLF4J or JCL.
GreyLog loggers are created by the
com.grey.logging.Factory class, which provides a number of
getLogger() factory methods.
All of them are based on a config file which is generically termed the
logging.xml
file (though it's not necessarily called that) and contains named entries, each of which specifies and defines a particular logger.
If you call a getLogger() variant that doesn't specify a config file, then the global default logging.xml file is used.
If you call a getLogger() variant that doesn't specify a named logger (or you specify a blank or null name), then a special logging.xml entry called the
default
logger is used.
The default entry need not exist (though it is recommended that you do define it) and if it doesn't GreyLog will create a logger with default settings, which can be influenced by system properties (see the default constructor in the
com.grey.logging.Parameters
source code), but is typically the standard-output stream.
If you specify a named logger other than default, and it doesn't exist in the logging.xml file, then a
SinkLogger instance is returned, which silently discards all messages written to it.
The first time the GreyLog framework tries to access the default logging.xml config file, it looks for it on the following search path, stopping on the first match:
• If the grey.logger.configfile system property is set, then it specifies the pathname.
• ./logging.xml (ie. look in current directory)
• ./conf/logging.xml
• $HOME/logging.xml
• Look for it on the classpath as ./logging.xml.
If still not found, then getLogger() calls will treat all requested loggers as non-existent, so as described above, any logger other than default will get mapped to the SinkLogger.
The example below illustrates the structure of the logging.xml config file, and the logger name specified in the
getLogger() call is used to select the matching
logger
block.
<loggers> <logger name="default"> <file class="com.grey.logging.MTLatinLogger">%stdout%</file> </logger> <logger name="mylogger1"> <file level="trc" rot="daily">%DIRLOG%/app.log</file> </logger> <logger name="mylogger2"> <file maxfile="10M">app2.log</file> </logger> </loggers> |
The value of the
file
element specifies the pathname of the output file, which is actually a template name in which the timestamp gets embedded.
It can also take the special values
%stdout% and
%stderr%,
which will direct logging output to the process's standard-output or standard-error instead.
If it contains the special token
%DIRLOG%, that will be replaced by the value of the
grey.logger.dir system property.
If it contains the special token
%DIRTMP%, that will be replaced by the value of
com.grey.base.config.SysProps.TMPDIR.
If it contains the special token
%TID%, that will be replaced by the Java thread ID
(Thread.currentThread().getId()).
The attributes of the
file
elements are shown below.
The default values for all these config attributes are determined via system properties. See the
com.grey.logging.Parameters
source code.
If the system property
grey.logger.diagnostics
is set to Yes, then progress messages on the search for the
logging.xml file and the process of creating a logger will be printed to the process's standard-output.
If the system property
grey.logger.sinkstdio
is set to Yes, then instead of missing loggers (ie. specified name not found in logging.xml file) being mapped to the SinkLogger, they will be mapped to a logger with default settings, ie. the same type of logger that would be created for a missing
default logger (which as explained above, is typically on stdout).
This can be useful if you don't want to lose any logging output regardless of your logging.xml config.
This section describes how GreyLog instances can be redirected to external facades, such as SLF4J, JCL and JUL.
Redirection is based on the logging.xml
class
attribute described above:
•
class="com.grey.logging.adapters.AdapterSLF4J":
Creates an SLF4J logger with the same name as the GreyLog logger.
•
class="com.grey.logging.adapters.AdapterJCL":
Creates a JCL logger with the same name as the GreyLog logger.
The net effect is that the calling code will still have a GreyLog logger instance
(ie. of type com.grey.logging.Logger)
but all log messages will be forwarded to the external logger.
If you already manage and configure all your logging via another framework, this allows GreyLog users to tap into that without changing any Java code.
Simply modify the logging.xml and the GreyLog logger joins the external logging framework.
This section is the reverse of the above, and describes how external facades such as SLF4J, JCL and JUL can be redirected to GreyLog.
As such, this is not relevant to NAF, which invokes the GreyLog framework directly, but it allows GreyLog to be transparently plugged into non-NAF code, or any code which doesn't have static (compile-time) bindings to GreyLog.
While the GreyLog framework itself has nothing to do with
SLF4J,
it includes an adapter library
(see the
greylog-slf4j
Maven project)
which enables it to act as underlying logger for SLF4J.
Simply put the greylog-slf4j JAR on your classpath ahead of any other SLF4J bindings, and all instantiations of SLF4J loggers will be redirected to the GreyLog framework.
That is, calls to
org.slf4j.LoggerFactory.getLogger(name)
will get mapped to
com.grey.logging.Factory.getLogger(name)
and as explained above, that will load the default
logging.xml
file.
Applications based on Commons Logging (JCL) can bind to the GreyLog framework by including the
jcl-over-slf4j
and
slf4j-api
JARs on their classpath, in addition to the
greylog-slf4j
JAR.
Applications based on the JDK's built-in JUL
(java.util.logging)
framework can bind to the GreyLog framework by including the
jul-to-slf4j
and
slf4j-api
JARs on their classpath, in addition to the
greylog-slf4j
JAR.