View source code Display the source code in std/experimental/logger.d from which this page was generated on github. Improve this page Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone. Page wiki View or edit the community-maintained wiki page associated with this page.

Module std.experimental.logger

Implements logging facilities.

Authors

Robert burner Schadek

Basic Logging

Message logging is a common approach to expose runtime information of a program. 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.experimental.logger;

void main() {
    log("Hello World");
}

This will print a message to the stderr device. The message will contain the filename, the linenumber, the name of the surrounding function, the time and 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 named functions to log data.

The names of the functions are as follows:

  • log
  • trace
  • info
  • warning
  • critical
  • fatal
  • The default Logger will by default log to stderr and has a default LogLevel of LogLevel.all. The default Logger can be accessed by using the property called sharedLog. This property a reference to the current default Logger. This reference can be used to assign a new default Logger.

    sharedLog = new FileLogger("New_Default_Log_File.log");
    

    Additional Logger can be created by creating a new instance of the required Logger.

    Logging Fundamentals

    LogLevel

    The LogLevel of an log call can be defined in two ways. The first is by calling log and passing the LogLevel explicit as the first argument. The second way of setting the LogLevel of a log call, is by calling either trace, info, warning, critical, or fatal. The log call will than have the respective LogLevel. If no LogLevel is defined the log call will use the current LogLevel of the used Logger. If data is logged with LogLevel fatal by default an Error will be thrown. This behaviour can be modified by using the member fatalHandler to assign a custom delegate to handle log call with LogLevel fatal.

    Conditional Logging

    Conditional logging can be achieved be passing a bool as first argument to a log function. If conditional logging is used the condition must be true in order to have the log message logged.

    In order to combine an explicit LogLevel passing with conditional logging, 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 or equal to than the LogLevel of the used Logger and additionally if the LogLevel of the log message is greater 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 the LogLevel of a Logger use the logLevel property of the logger.

    Printf Sytle Logging

    If printf-style logging is needed add a f to the logging call, such as myLogger.infof("Hello %s", "world"); or %d", 1337) The additional f enables printf-style logging for call combinations of explicit LogLevel and conditional logging functions and methods.

    Thread Local Redirection

    Calls to the free standing log functions are not directly forwarded to the global Logger sharedLog. Actually, a thread local Logger of type StdForwardLogger process the log call and then, by default, forward the created Logger.LogEntry to the sharedLog Logger. The thread local Logger is accessable by the stdThreadLocalLog property. This property allows to assign user defined Logger. The default LogLevel of the stdThreadLocalLog Logger is LogLevel.all and it will therefore forward all messaged to the sharedLog Logger. The LogLevel of the stdThreadLocalLog can be used to filter log calls before they reach the sharedLog Logger.

    User Defined Logger

    To customize the Logger behavior, create a new class that inherits from the abstract Logger class, and implements the writeLogMsg method.

    class MyCustomLogger : Logger
    {
        this(string newName, LogLevel lv) @safe
        {
            super(newName, lv);
        }
    
        override void writeLogMsg(ref LogEntry payload)
        {
            // log message in my custom way
        }
    }
    
    auto logger = new MyCustomLogger();
    logger.log("Awesome log message");
    

    To gain more precise control over the logging process, additionally to overwriting the writeLogMsg method the methods beginLogMsg, logMsgPart and finishLogMsg can be overwritten.

    Compile Time Disabling of Logger

    In order to disable logging at compile time, pass StdLoggerDisableLogging as a version argument to the D compiler when compiling your program code. This will disable all logging functionality. Specific LogLevel can be disabled at compile time as well. In order to disable logging with the trace LogLevel pass StdLoggerDisableTrace as a version. The following table shows which version statement disables which LogLevel.
    LogLevel.trace StdLoggerDisableTrace
    LogLevel.info StdLoggerDisableInfo
    LogLevel.warning StdLoggerDisableWarning
    LogLevel.error StdLoggerDisableError
    LogLevel.critical StdLoggerDisableCritical
    LogLevel.fatal StdLoggerDisableFatal
    Such a version statement will only disable logging in the associated compile unit.

    Provided Logger

    By default four Logger implementations are given. The FileLogger logs data to files. It can also be used to log to stdout and stderr as these devices are files as well. A Logger that logs to stdout can therefore 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 log calls to its stored Logger. The NullLogger does not do anything. It will never log a message and will never throw on a log call with LogLevel error.

    License

    Boost License 1.0.

    Comments