1 /** 
2  * Core logging services
3  *
4  * Authors: Tristan Brice Velloza Kildaire (deavmi)
5  */
6 module dlog.core;
7 
8 import std.container.slist : SList;
9 import core.sync.mutex : Mutex;
10 
11 /** 
12  * The base message type
13  */
14 public abstract class Message
15 {
16 
17 }
18 
19 /** 
20  * Defines the filtering
21  * interface
22  */
23 public interface Filter
24 {
25     /** 
26      * Filters the given message
27      * returning a verdict
28      * based on it
29      *
30      * Params:
31      *   message = the message
32      * Returns: the verdct
33      */
34     public bool filter(Message message);
35 }
36 
37 /** 
38  * Defines the message
39  * transformation interface
40  */
41 public interface Transform
42 {
43     /** 
44      * Transforms the given message
45      *
46      * Params:
47      *   message = the message input
48      * Returns: the transformed
49      * message
50      */
51     public Message transform(Message message);
52 }
53 
54 /** 
55  * Defines the interface
56  * for handling messages
57  */
58 public interface Handler
59 {
60     /** 
61      * Handles the given message
62      *
63      * Params:
64      *   message = the message to
65      * handle
66      */
67     public void handle(Message message);
68 }
69 
70 /** 
71  * Defines the base logger
72  * and functionality associated
73  * with it
74  */
75 public abstract class Logger
76 {
77     private SList!(Transform) transforms;
78     private SList!(Filter) filters;
79     private SList!(Handler) handlers;
80     private Mutex lock; // Lock for attached handlers, filters and transforms
81 
82     /** 
83      * Constructs a new logger
84      */
85     this()
86     {
87         this.lock = new Mutex();
88     }
89 
90     // TODO: Handle duplicate?
91     /** 
92      * Adds the given transform
93      *
94      * Params:
95      *   transform = the transform
96      * to add
97      */
98     public final void addTransform(Transform transform)
99     {
100         scope(exit)
101         {
102             this.lock.unlock();
103         }
104 
105         this.lock.lock();
106 
107         this.transforms.insertAfter(this.transforms[], transform);
108     }
109 
110     // TODO: Hanmdle not found explicitly?
111     /** 
112      * Removes the given transform
113      *
114      * Params:
115      *   transform = the transform
116      * to remove
117      */
118     public final void removeTransform(Transform transform)
119     {
120         scope(exit)
121         {
122             this.lock.unlock();
123         }
124 
125         this.lock.lock();
126 
127         this.transforms.linearRemoveElement(transform);
128     }
129 
130     // TODO: Handle duplicate?
131 
132     /** 
133      * Adds the given filter
134      *
135      * Params:
136      *   filter = the filter
137      * to add
138      */
139     public final void addFilter(Filter filter)
140     {
141         scope(exit)
142         {
143             this.lock.unlock();
144         }
145 
146         this.lock.lock();
147 
148         this.filters.insertAfter(this.filters[], filter);
149     }
150 
151     // TODO: Hanmdle not found explicitly?
152 
153     /** 
154      * Removes the given filter
155      *
156      * Params:
157      *   filter = the filter
158      * to remove
159      */
160     public final void removeFilter(Filter filter)
161     {
162         scope(exit)
163         {
164             this.lock.unlock();
165         }
166 
167         this.lock.lock();
168 
169         this.filters.linearRemoveElement(filter);
170     }
171 
172     // TODO: Handle duplicate?
173 
174     /** 
175      * Adds the given handler
176      *
177      * Params:
178      *   handler = the handler
179      * to add
180      */
181     public final void addHandler(Handler handler)
182     {
183         scope(exit)
184         {
185             this.lock.unlock();
186         }
187 
188         this.lock.lock();
189 
190         this.handlers.insertAfter(this.handlers[], handler);
191     }
192 
193     // TODO: Hanmdle not found explicitly?
194 
195     /** 
196      * Removes the given handler
197      *
198      * Params:
199      *   handler = the handler
200      * to remove
201      */
202     public final void removeHandler(Handler handler)
203     {
204         scope(exit)
205         {
206             this.lock.unlock();
207         }
208 
209         this.lock.lock();
210 
211         this.handlers.linearRemoveElement(handler);
212     }
213 
214     /** 
215      * Logs the provided message by processing
216      * it through all the filters, and if
217      * the verdict is `true` then transforms
218      * the message via all transformers
219      * and finally dispatches said message
220      * to all attached handlers
221      *
222      * Params:
223      *   message = the message
224      */
225     public final void log(Message message)
226     {
227         scope(exit)
228         {
229             this.lock.unlock();
230         }
231 
232         this.lock.lock();
233 
234         foreach(Filter filter; this.filters)
235         {
236             if(!filter.filter(message))
237             {
238                 return;
239             }
240         }
241 
242         Message curMessage = message;
243         foreach(Transform transform; this.transforms)
244         {
245             curMessage = transform.transform(curMessage);
246         }
247 
248         foreach(Handler handler; this.handlers)
249         {
250             handler.handle(curMessage);
251         }
252     }
253 }