1 /++ 2 Package provides static `Logger logger` 3 4 Logger functions: 5 6 void logger.error(Args...)( Args args ); 7 void logger.warn (Args...)( Args args ); 8 void logger.info (Args...)( Args args ); 9 void logger.Debug(Args...)( Args args ); 10 void logger.trace(Args...)( Args args ); 11 12 ... 13 logger.info( "format %s %f %d", "str", 3.14, 4 ); 14 logger.Debug( "some info" ); 15 logger.trace( 12 ); 16 ... 17 18 If program starts as `./program --log trace` output must be like this 19 20 [000000.111427128][ INFO][module.function]: format str 3.14 4 21 [000000.111427128][DEBUG][module.function]: some info 22 [000000.111938579][TRACE][module.function]: 12 23 24 If log function has string as first argument it tries to format other args to this 25 string, if it failed print converted to string and concatenated args. 26 27 If program starts as `./program --log debug` output must be like this (without trace) 28 29 [000000.111427128][ INFO][module.function]: format str 3.14 4 30 31 Flag `--log` used for setting max level of logging output. 32 Default level is `error`. If log function called with greater level it's skipped. 33 Level has attitudes `off < fatal < error < warn < info < debug < trace`. 34 35 Flag `--log` can be used with module name `./program --log draw.point:debug`. 36 It will set `debug` level for module `draw.point` and default to other. 37 38 Flag `--log-use-min` is boolean flag. It forces logging system to skip output from 39 all child modules if their level greater than parent. Default is `false`. 40 41 `./program --log trace --log draw:info --log draw.point:trace --log-use-min=true` 42 skips all output from `logger.trace` and `logger.Debug` from whole draw.point, 43 and doesn't skip from other modules. 44 45 `./program --log trace --log draw:info --log draw.point:trace` allow `log_trace` 46 and `log_debug` only from `draw.point` from module `draw`. For other modules in 47 `draw` sets level `info` 48 49 You can compile program with `version=logonlyerror` for skip all 50 `trace`, `debug`, `info` and `warn` outputs in logger. It can improve program 51 release speed. 52 53 ## Class logging 54 55 Module provides some functional for useful logging classes. 56 57 Example: 58 59 module x; 60 import des.util.logger; 61 class A 62 { 63 mixin ClassLogger; 64 void func() { logger.trace( "hello" ); } 65 } 66 67 module y; 68 import x; 69 class B : A { } 70 71 auto b = new B; 72 ... 73 b.func(); 74 75 outputs: 76 77 [000000.148628473][TRACE][x.A.func]: hello 78 79 If create instance logger 80 81 class B : A { this(){ logger = new InstanceLogger(this); } } 82 83 outputs: 84 85 [000000.148628473][TRACE][y.B.func]: hello 86 87 If create instance logger with instance name 88 89 class B : A { this(){ logger = new InstanceLogger(this,"my object"); } } 90 91 outputs: 92 93 [000000.148628473][TRACE][y.B.[my object].func]: hello 94 95 If create instance full logger 96 97 class B : A { this(){ logger = new InstanceFullLogger(this); } } 98 99 outputs: 100 [000000.148628473][TRACE][y.B.[x.A.func]]: hello 101 102 If create instance full logger with name 103 104 class B : A { this(){ logger = new InstanceFullLogger(this,"name"); } } 105 106 outputs: 107 108 [000000.148628473][TRACE][y.B.[name].[x.A.func]]: hello 109 110 Flag `--log` can get full emitter string `y.B.[name].[x.A.func]`. 111 112 ./program --log "y.B.[one]:trace" --log "y.B.[two]:debug" 113 +/ 114 module des.util.logsys; 115 116 public 117 { 118 import des.util.logsys.base; 119 import des.util.logsys.logcls; 120 import des.util.logsys.output; 121 } 122 123 import des.util.logsys.rule; 124 125 /// for simple adding logging to class 126 mixin template ClassLogger() 127 { 128 static if( !is( typeof( __logger ) ) ) 129 { 130 private Logger __logger; 131 protected nothrow final @property 132 { 133 const(Logger) logger() const 134 { 135 mixin( "static import " ~ __MODULE__ ~ ";" ); 136 if( __logger is null ) 137 mixin( "return " ~ __MODULE__ ~ ".logger;" ); 138 else return __logger; 139 } 140 void logger( Logger lg ) { __logger = lg; } 141 } 142 } 143 } 144 145 Logger logger; /// 146 147 static this() { logger = new Logger; } 148 149 shared static this() 150 { 151 if( logrule !is null ) return; 152 153 import core.runtime, std.getopt; 154 import std.stdio; 155 import std.file; 156 157 logrule = new shared Rule; 158 159 auto args = thisExePath ~ Runtime.args; 160 string[] logging; 161 bool use_minimal = false; 162 bool console_color = true; 163 string logfile; 164 165 try 166 { 167 getopt( args, 168 std.getopt.config.passThrough, 169 "log", &logging, 170 "log-use-min", &use_minimal, 171 "log-console-color", &console_color, 172 "log-file", &logfile, 173 ); 174 } 175 catch( Exception e ) stderr.writefln( "bad log arguments: %s", e.msg ); 176 177 logoutput = new shared LogOutputHandler( console_color ); 178 179 if( logfile.length ) 180 logoutput.append( "logfile", new shared FileLogOutput(logfile) ); 181 182 logrule.use_minimal = use_minimal; 183 184 foreach( ln; logging ) 185 { 186 auto sp = ln.split(":"); 187 if( sp.length == 1 ) 188 { 189 try logrule.setLevel( toLogLevel( sp[0] ) ); 190 catch( Exception e ) 191 stderr.writefln( "log argument '%s' can't conv to LogLevel: %s", ln, e.msg ); 192 } 193 else if( sp.length == 2 ) 194 { 195 try 196 { 197 auto level = toLogLevel( sp[1] ); 198 logrule.setLevel( level, sp[0] ); 199 } 200 catch( Exception e ) 201 stderr.writefln( "log argument '%s' can't conv '%s' to LogLevel: %s", ln, sp[1], e.msg ); 202 } 203 else stderr.writefln( "bad log argument: %s" ); 204 } 205 206 if( logging.length ) 207 { 208 writeln( "[log use min]: ", use_minimal ); 209 writeln( "[log rules]:\n", logrule.print() ); 210 } 211 }