Robert burner SchadekBasic Logging
Message logging is a common approach to expose runtime information of aprogram. Logging should be easy, but also flexible and powerful, therefore
D provides a standard interface for logging.
The easiest way to create a log message is to write:
import std.logger;void main() { info("Hello World");}This will print a message to the
stderr device. The message will containthe filename, the line number, the name of the surrounding function, the timeand the message.
More complex log call can go along the lines like:
log("Logging to the sharedLog with its default LogLevel");logf(LogLevel.info, 5 < 6,"%s to the sharedLog with its LogLevel.info","Logging");info("Logging to the sharedLog with its info LogLevel");warning(5 < 6,"Logging to the sharedLog with its LogLevel.warning if 5 is less than 6");error("Logging to the sharedLog with its error LogLevel");errorf("Logging %s the sharedLog %s its error LogLevel","to","with");critical("Logging to the"," sharedLog with its error LogLevel");fatal("Logging to the sharedLog with its fatal LogLevel");auto fLogger =new FileLogger("NameOfTheLogFile");fLogger.log("Logging to the fileLogger with its default LogLevel");fLogger.info("Logging to the fileLogger with its default LogLevel");fLogger.warning(5 < 6,"Logging to the fileLogger with its LogLevel.warning if 5 is less than 6");fLogger.warningf(5 < 6,"Logging to the fileLogger with its LogLevel.warning if %s is %s than 6", 5,"less");fLogger.critical("Logging to the fileLogger with its info LogLevel");fLogger.log(LogLevel.trace, 5 < 6,"Logging to the fileLogger"," with its default LogLevel if 5 is less than 6");fLogger.fatal("Logging to the fileLogger with its warning LogLevel");Additionally, this example shows how a new
FileLogger is created.Individual
Logger and the global log functions share commonly namedfunctions to log data.
The names of the functions are as follows:
- log
- trace
- info
- warning
- error
- critical
- fatal
The default
Logger will by default log to
stderr and has a default
LogLevel of
LogLevel.info. The default Logger can be accessed byusing the property called
sharedLog. This property is a reference to thecurrent default
Logger. This reference can be used to assign a newdefault
Logger.
sharedLog =newshared FileLogger("New_Default_Log_File.log");Additional
Logger can be created by creating a new instance of therequired
Logger.
Logging Fundamentals
LogLevel
The
LogLevel of a log call can be defined in two ways. The first is bycalling
log and passing the
LogLevel explicitly as the first argument.The second way of setting the
LogLevel of alog call, is by calling either
trace,
info,
warning,
critical, or
fatal. The log call will then have the respective
LogLevel. If no
LogLevel is defined the log call will use thecurrent
LogLevel of the used
Logger. If data is logged with
LogLevelfatal by default an
Error will be thrown.This behaviour can be modified by using the member
fatalHandler toassign a custom delegate to handle log call with
LogLevelfatal.
Conditional Logging
Conditional logging can be achieved be passing a
bool as firstargument to a log function. If conditional logging is used the condition mustbe
true in order to have the log message logged.
In order to combine an explicit
LogLevel passing with conditionallogging, the
LogLevel has to be passed as first argument followed by the
bool.
Filtering Log Messages
Messages are logged if the
LogLevel of the log message is greater than orequal to the
LogLevel of the used
Logger and additionally if the
LogLevel of the log message is greater than or equal to the global
LogLevel.If a condition is passed into the log call, this condition must be true.
The global
LogLevel is accessible by using
globalLogLevel.To assign a
LogLevel of a
Logger use the
logLevel property ofthe logger.
Printf Style Logging
If
printf-style logging is needed add a
f to the logging call, such as
myLogger.infof("Hello %s", "world"); or
fatalf("errno %d", 1337).The additional
f appended to the function name enables
printf-stylelogging for all combinations of explicit
LogLevel and conditionallogging functions and methods.
Thread Local Redirection
Calls to the free standing log functions are not directly forwarded to theglobal
LoggersharedLog. Actually, a thread local
Logger oftype
StdForwardLogger processes the log call and then, by default, forwardsthe created
Logger.LogEntry to the
sharedLogLogger.The thread local
Logger is accessible by the
stdThreadLocalLogproperty. This property allows to assign user defined
Logger. The default
LogLevel of the
stdThreadLocalLogLogger is
LogLevel.alland it will therefore forward all messages to the
sharedLogLogger.The
LogLevel of the
stdThreadLocalLog can be used to filter logcalls before they reach the
sharedLogLogger.
User Defined Logger
To customize the
Logger behavior, create a new
class that inherits fromthe abstract
Loggerclass, and implements the
writeLogMsgmethod.
class MyCustomLogger : Logger{this(LogLevel lv) @safe {super(lv); }overridevoid writeLogMsg(ref LogEntry payload) {// log message in my custom way }}autologger =new MyCustomLogger(LogLevel.info);logger.log("Awesome log message with LogLevel.info");To gain more precise control over the logging process, additionally tooverriding the
writeLogMsg method the methods
beginLogMsg,
logMsgPart and
finishLogMsg can be overridden.
Provided Logger
By default four
Logger implementations are given. The
FileLoggerlogs data to files. It can also be used to log to
stdout and
stderras these devices are files as well. A
Logger that logs to
stdout cantherefore be created by
new FileLogger(stdout).The
MultiLogger is basically an associative array of
strings to
Logger. It propagates log calls to its stored
Logger. The
ArrayLogger contains an array of
Logger and also propagates logcalls to its stored
Logger. The
NullLogger does not do anything. Itwill never log a message and will never throw on a log call with
LogLevelerror.