1 module des.util.logsys.logcls; 2 3 import std.traits : EnumMembers; 4 import std..string : toLower, format, split; 5 import std.stdio : stderr; 6 7 import des.util.logsys.base; 8 import des.util.logsys.output; 9 10 /// base logger class 11 class Logger 12 { 13 /// 14 mixin( getLogFunctions ); 15 16 protected: 17 18 /// check log message level allowed with current rules for emmiter 19 final void procMessage( in LogMessage lm ) const nothrow 20 { 21 try if( logrule.allowedLevel( lm.emitter ) >= lm.level ) writeLog( lm ); 22 catch( Exception e ) writeLogFailPrint(e); 23 } 24 25 /// exception processing 26 void writeLogFailPrint( Exception e ) const nothrow 27 { 28 try stderr.writefln( "[INTERNAL LOG EXCEPTION]: %s", e ); 29 catch(Exception){} 30 } 31 32 /// write log to logoutput 33 void writeLog( in LogMessage lm ) const 34 { logoutput( chooseOutputName(lm), lm ); } 35 36 /// logger can chouse output name 37 string chooseOutputName( in LogMessage lvl ) const 38 { return LogOutputHandler.console_name; } 39 40 /// transform caller func name to emitter name 41 string getEmitterName( string func_name ) const nothrow 42 in{ assert( func_name.length ); } 43 out(ret){ assert( ret.length ); } 44 body { return func_name; } 45 46 private static string getLogFunctions() @property 47 { 48 string fnc = ` 49 void %1$s( string fnc=__FUNCTION__, Args... )( Args args ) const nothrow 50 { 51 version(logonlyerror) 52 { 53 static if( LogMessage.Level.%2$s <= LogMessage.Level.ERROR ) 54 procMessage( LogMessage( getEmitterName(fnc), __ts, LogMessage.Level.%2$s, ntFormat(args) ) ); 55 } 56 else procMessage( LogMessage( getEmitterName(fnc), __ts, LogMessage.Level.%2$s, ntFormat(args) ) ); 57 } 58 `; 59 60 string ret; 61 foreach( lvl; [EnumMembers!(LogMessage.Level)] ) 62 { 63 auto slvl = to!string(lvl); 64 auto fname = checkReservedName( slvl.toLower ); 65 ret ~= format( fnc, fname, slvl ); 66 } 67 return ret; 68 } 69 } 70 71 /// logger for class instances 72 class InstanceLogger : Logger 73 { 74 protected: 75 string class_name; /// 76 string inst_name; /// 77 78 public: 79 80 /// 81 this( Object obj, string inst="" ) 82 { 83 class_name = typeid(obj).name; 84 inst_name = inst; 85 } 86 87 /// 88 this( string obj, string inst="" ) 89 { 90 class_name = obj; 91 inst_name = inst; 92 } 93 94 nothrow @property 95 { 96 /// 97 void instance( string i ) { inst_name = i; } 98 99 /// 100 string instance() const { return inst_name; } 101 } 102 103 protected: 104 105 /// Returns: module + class_name + inst_name (if it exists) 106 override string getEmitterName( string name ) const nothrow 107 { 108 try return fullEmitterName ~ "." ~ name.split(".")[$-1]; 109 catch(Exception e) return fullEmitterName; 110 } 111 112 string fullEmitterName() const nothrow @property 113 { return class_name ~ (inst_name.length?".["~inst_name~"]":""); } 114 } 115 116 /// logger for class instances with extended emitter name 117 class InstanceFullLogger : InstanceLogger 118 { 119 /// 120 this( Object obj, string inst="" ) { super(obj,inst); } 121 122 /// 123 this( string obj, string inst="" ) { super(obj,inst); } 124 125 protected: 126 127 /// Returns: module + class_name + inst_name (if it exists) + call function name 128 override string getEmitterName( string name ) const nothrow 129 { return fullEmitterName ~ ".[" ~ name ~ "]"; } 130 }