1 module des.log.rule; 2 3 import std.algorithm : min; 4 import std.string : split, join; 5 6 import des.log.base; 7 8 /// store rules for logging 9 synchronized class Rule 10 { 11 package: 12 shared Rule parent; /// 13 14 LogLevel level = LogLevel.ERROR; /// 15 shared Rule[string] inner; /// 16 17 bool use_minimal = true; /// 18 19 public: 20 21 /// 22 this( shared Rule parent = null ) 23 { 24 this.parent = parent; 25 if( parent ) 26 this.level = parent.level; 27 } 28 29 @property 30 { 31 /// 32 bool useMinimal() const 33 { 34 if( parent !is null ) 35 return parent.useMinimal(); 36 else return use_minimal; 37 } 38 39 /// 40 void useMinimal( bool um ) 41 { 42 if( parent !is null ) 43 parent.useMinimal = um; 44 else use_minimal = um; 45 } 46 } 47 48 /// setting allowed level for emitter (create new inner Rule), if emitter is "" sets self level 49 void setLevel( LogLevel lvl, string emitter="" ) 50 { 51 auto addr = splitAddress( emitter ); 52 if( addr[0].length == 0 ) { level = lvl; return; } 53 auto iname = addr[0]; 54 if( iname !in inner ) inner[iname] = new shared Rule(this); 55 inner[iname].setLevel( lvl, addr[1] ); 56 } 57 58 /// if emitter is "" returns self level 59 LogLevel allowedLevel( string emitter="" ) 60 { 61 auto addr = splitAddress( emitter ); 62 if( addr[0].length == 0 ) return level; 63 auto iname = addr[0]; 64 if( iname !in inner ) return level; 65 if( useMinimal ) 66 return min( level, inner[iname].allowedLevel( addr[1] ) ); 67 else 68 return inner[iname].allowedLevel( addr[1] ); 69 } 70 71 string print( string offset="" ) const 72 { 73 string ret = format( "%s", level ); 74 foreach( key, val; inner ) 75 ret ~= format( "\n%s%s : %s", offset, key, val.print( offset ~ mlt(" ",key.length) ) ); 76 return ret; 77 } 78 79 protected: 80 81 /// 82 static string[2] splitAddress( string emitter ) 83 { 84 auto addr = emitter.split("."); 85 if( addr.length == 0 ) return ["",""]; 86 if( addr.length == 1 ) return [addr[0],""]; 87 88 return [ addr[0], addr[1..$].join(".") ]; 89 } 90 } 91 92 private T[] mlt(T)( T[] val, size_t cnt ) nothrow 93 { 94 T[] buf; 95 foreach( i; 0 .. cnt ) buf ~= val; 96 return buf; 97 } 98 99 unittest { assert( " ", mlt( " ", 4 ) ); } 100 101 /// 102 unittest 103 { 104 auto r = new shared Rule; 105 106 r.setLevel( LogLevel.INFO ); 107 r.setLevel( LogLevel.TRACE, "des.gl" ); 108 r.setLevel( LogLevel.WARN, "des" ); 109 110 assert( r.allowedLevel() == LogLevel.INFO ); 111 assert( r.allowedLevel("des") == LogLevel.WARN ); 112 assert( r.allowedLevel("des.gl") == LogLevel.WARN ); 113 114 r.use_minimal = false; 115 116 assert( r.allowedLevel() == LogLevel.INFO ); 117 assert( r.allowedLevel("des") == LogLevel.WARN ); 118 assert( r.allowedLevel("des.gl") == LogLevel.TRACE ); 119 }