1 // Written in the D programming language. 2 /** 3 Implements logging facilities. 4 5 Copyright: Copyright Robert "burner" Schadek 2013 -- 6 License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 7 Authors: $(HTTP www.svs.informatik.uni-oldenburg.de/60865.html, Robert burner Schadek) 8 9 $(H3 Basic Logging) 10 11 Message logging is a common approach to expose runtime information of a 12 program. Logging should be easy, but also flexible and powerful, therefore 13 `D` provides a standard interface for logging. 14 15 The easiest way to create a log message is to write: 16 ------------- 17 import std.experimental.logger; 18 19 void main() { 20 log("Hello World"); 21 } 22 ------------- 23 This will print a message to the `stderr` device. The message will contain 24 the filename, the line number, the name of the surrounding function, the time 25 and the message. 26 27 More complex log call can go along the lines like: 28 ------------- 29 log("Logging to the sharedLog with its default LogLevel"); 30 logf(LogLevel.info, 5 < 6, "%s to the sharedLog with its LogLevel.info", "Logging"); 31 info("Logging to the sharedLog with its info LogLevel"); 32 warning(5 < 6, "Logging to the sharedLog with its LogLevel.warning if 5 is less than 6"); 33 error("Logging to the sharedLog with its error LogLevel"); 34 errorf("Logging %s the sharedLog %s its error LogLevel", "to", "with"); 35 critical("Logging to the"," sharedLog with its error LogLevel"); 36 fatal("Logging to the sharedLog with its fatal LogLevel"); 37 38 auto fLogger = new FileLogger("NameOfTheLogFile"); 39 fLogger.log("Logging to the fileLogger with its default LogLevel"); 40 fLogger.info("Logging to the fileLogger with its default LogLevel"); 41 fLogger.warning(5 < 6, "Logging to the fileLogger with its LogLevel.warning if 5 is less than 6"); 42 fLogger.warningf(5 < 6, "Logging to the fileLogger with its LogLevel.warning if %s is %s than 6", 5, "less"); 43 fLogger.critical("Logging to the fileLogger with its info LogLevel"); 44 fLogger.log(LogLevel.trace, 5 < 6, "Logging to the fileLogger"," with its default LogLevel if 5 is less than 6"); 45 fLogger.fatal("Logging to the fileLogger with its warning LogLevel"); 46 ------------- 47 Additionally, this example shows how a new `FileLogger` is created. 48 Individual `Logger` and the global log functions share commonly named 49 functions to log data. 50 51 The names of the functions are as follows: 52 $(UL 53 $(LI `log`) 54 $(LI `trace`) 55 $(LI `info`) 56 $(LI `warning`) 57 $(LI `critical`) 58 $(LI `fatal`) 59 ) 60 The default `Logger` will by default log to `stderr` and has a default 61 `LogLevel` of `LogLevel.all`. The default Logger can be accessed by 62 using the property called `sharedLog`. This property is a reference to the 63 current default `Logger`. This reference can be used to assign a new 64 default `Logger`. 65 ------------- 66 sharedLog = new FileLogger("New_Default_Log_File.log"); 67 ------------- 68 69 Additional `Logger` can be created by creating a new instance of the 70 required `Logger`. 71 72 $(H3 Logging Fundamentals) 73 $(H4 LogLevel) 74 The `LogLevel` of a log call can be defined in two ways. The first is by 75 calling `log` and passing the `LogLevel` explicitly as the first argument. 76 The second way of setting the `LogLevel` of a 77 log call, is by calling either `trace`, `info`, `warning`, 78 `critical`, or `fatal`. The log call will then have the respective 79 `LogLevel`. If no `LogLevel` is defined the log call will use the 80 current `LogLevel` of the used `Logger`. If data is logged with 81 `LogLevel` `fatal` by default an `Error` will be thrown. 82 This behaviour can be modified by using the member `fatalHandler` to 83 assign a custom delegate to handle log call with `LogLevel` `fatal`. 84 85 $(H4 Conditional Logging) 86 Conditional logging can be achieved be passing a `bool` as first 87 argument to a log function. If conditional logging is used the condition must 88 be `true` in order to have the log message logged. 89 90 In order to combine an explicit `LogLevel` passing with conditional 91 logging, the `LogLevel` has to be passed as first argument followed by the 92 `bool`. 93 94 $(H4 Filtering Log Messages) 95 Messages are logged if the `LogLevel` of the log message is greater than or 96 equal to the `LogLevel` of the used `Logger` and additionally if the 97 `LogLevel` of the log message is greater than or equal to the global `LogLevel`. 98 If a condition is passed into the log call, this condition must be true. 99 100 The global `LogLevel` is accessible by using `globalLogLevel`. 101 To assign a `LogLevel` of a `Logger` use the `logLevel` property of 102 the logger. 103 104 $(H4 Printf Style Logging) 105 If `printf`-style logging is needed add a $(B f) to the logging call, such as 106 $(D myLogger.infof("Hello %s", "world");) or $(D fatalf("errno %d", 1337)). 107 The additional $(B f) appended to the function name enables `printf`-style 108 logging for all combinations of explicit `LogLevel` and conditional 109 logging functions and methods. 110 111 $(H4 Thread Local Redirection) 112 Calls to the free standing log functions are not directly forwarded to the 113 global `Logger` `sharedLog`. Actually, a thread local `Logger` of 114 type `StdForwardLogger` processes the log call and then, by default, forwards 115 the created `Logger.LogEntry` to the `sharedLog` `Logger`. 116 The thread local `Logger` is accessible by the `stdThreadLocalLog` 117 property. This property allows to assign user defined `Logger`. The default 118 `LogLevel` of the `stdThreadLocalLog` `Logger` is `LogLevel.all` 119 and it will therefore forward all messages to the `sharedLog` `Logger`. 120 The `LogLevel` of the `stdThreadLocalLog` can be used to filter log 121 calls before they reach the `sharedLog` `Logger`. 122 123 $(H3 User Defined Logger) 124 To customize the `Logger` behavior, create a new `class` that inherits from 125 the abstract `Logger` `class`, and implements the `writeLogMsg` 126 method. 127 ------------- 128 class MyCustomLogger : Logger 129 { 130 this(LogLevel lv) @safe 131 { 132 super(lv); 133 } 134 135 override void writeLogMsg(ref LogEntry payload) 136 { 137 // log message in my custom way 138 } 139 } 140 141 auto logger = new MyCustomLogger(LogLevel.info); 142 logger.log("Awesome log message with LogLevel.info"); 143 ------------- 144 145 To gain more precise control over the logging process, additionally to 146 overriding the `writeLogMsg` method the methods `beginLogMsg`, 147 `logMsgPart` and `finishLogMsg` can be overridden. 148 149 $(H3 Compile Time Disabling of `Logger`) 150 In order to disable logging at compile time, pass `StdLoggerDisableLogging` as a 151 version argument to the `D` compiler when compiling your program code. 152 This will disable all logging functionality. 153 Specific `LogLevel` can be disabled at compile time as well. 154 In order to disable logging with the `trace` `LogLevel` pass 155 `StdLoggerDisableTrace` as a version. 156 The following table shows which version statement disables which 157 `LogLevel`. 158 $(TABLE 159 $(TR $(TD `LogLevel.trace` ) $(TD StdLoggerDisableTrace)) 160 $(TR $(TD `LogLevel.info` ) $(TD StdLoggerDisableInfo)) 161 $(TR $(TD `LogLevel.warning` ) $(TD StdLoggerDisableWarning)) 162 $(TR $(TD `LogLevel.error` ) $(TD StdLoggerDisableError)) 163 $(TR $(TD `LogLevel.critical` ) $(TD StdLoggerDisableCritical)) 164 $(TR $(TD `LogLevel.fatal` ) $(TD StdLoggerDisableFatal)) 165 ) 166 Such a version statement will only disable logging in the associated compile 167 unit. 168 169 $(H3 Provided Logger) 170 By default four `Logger` implementations are given. The `FileLogger` 171 logs data to files. It can also be used to log to `stdout` and `stderr` 172 as these devices are files as well. A `Logger` that logs to `stdout` can 173 therefore be created by $(D new FileLogger(stdout)). 174 The `MultiLogger` is basically an associative array of `string`s to 175 `Logger`. It propagates log calls to its stored `Logger`. The 176 `ArrayLogger` contains an array of `Logger` and also propagates log 177 calls to its stored `Logger`. The `NullLogger` does not do anything. It 178 will never log a message and will never throw on a log call with `LogLevel` 179 `error`. 180 181 Source: $(PHOBOSSRC std/experimental/logger/package.d) 182 */ 183 module std.experimental.logger; 184 185 public import std.experimental.logger.core; 186 public import std.experimental.logger.filelogger; 187 public import std.experimental.logger.multilogger; 188 public import std.experimental.logger.nulllogger;