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