1 /** 
2  * Defines some basic message
3  * types, filters and handlers
4  * that may be of use in
5  * some combination or
6  * seperate
7  *
8  * Authors: Tristan Brice Velloza Kildaire (deavmi)
9  */
10 module dlog.basic;
11 
12 import dlog.core;
13 import std.stdio : File;
14 
15 /** 
16  * Represents a basic message
17  * with log level information
18  * associated with it as well
19  * as text
20  */
21 public class BasicMessage : Message
22 {
23     /** 
24      * The text message
25      */
26     private string text;
27 
28     /** 
29      * Log level
30      */
31     private Level level;
32 
33     /** 
34      * Constructs a new `BasicMessage`
35      * with the given text and log level
36      *
37      * Params:
38      *   text = the message text
39      *   level = the log level (default
40      * is `Level.INFO`)
41      */
42     this(string text, Level level = Level.INFO)
43     {
44         this.text = text;
45         this.level = level;
46     }
47 
48     /** 
49      * Constructs an empty message
50      * with the highest log level
51      * (least verbose)
52      */
53     this()
54     {
55 
56     }
57 
58     /** 
59      * Sets the text
60      *
61      * Params:
62      *   text = the message's
63      * text
64      */
65     public void setText(string text)
66     {
67         this.text = text;
68     }
69 
70     /** 
71      * Returns the text
72      *
73      * Returns: the text
74      */
75     public string getText()
76     {
77         return this.text;
78     }
79 
80     /** 
81      * Returns the log level
82      *
83      * Returns: the level
84      */
85     public Level getLevel()
86     {
87         return this.level;
88     }
89 
90     /** 
91      * Sets the log level
92      *
93      * Params:
94      *   level = the level
95      */
96     public void setLevel(Level level)
97     {
98         this.level = level;
99     }
100 }
101 
102 /** 
103  * A file-based handler which
104  * writes `BasicMessage`(s)
105  * to a provided file
106  */
107 public class FileHandler : Handler
108 {
109     /** 
110      * File to write to
111      */
112     private File file;
113 
114     /** 
115      * Constrtucts a new
116      * `FileHandler` with
117      * the given file
118      *
119      * Params:
120      *   file = the file
121      */
122     this(File file)
123     {
124         this.file = file;
125     }
126 
127     /** 
128      * Handles the message, does a
129      * no-op if the message is
130      * not a kind-of `BasicMessage`
131      *
132      * Params:
133      *   message = the message
134      */
135     public void handle(Message message)
136     {
137         // Only handle BasicMessage(s)
138         BasicMessage bmesg = cast(BasicMessage)message;
139         if(bmesg)
140         {
141             file.write(bmesg.getText());
142         }
143     }
144 }
145 
146 /** 
147  * Logging level
148  */
149 public enum Level
150 {
151     /** 
152      * Error message
153      */
154     ERROR,
155 
156     /** 
157      * Informative message
158      */
159     INFO,
160 
161     /** 
162      * Warning message
163      */
164     WARN,
165 
166     /** 
167      * Debugging message
168      */
169     DEBUG
170 }
171 
172 /** 
173  * A level-based filter which
174  * has a predicate which operates
175  * on the value of a pointed-to
176  * `Level` variable
177  */
178 private class LevelFilter : Filter
179 {
180     /** 
181      * Address of the level var
182      */
183     private Level* level;
184 
185     /** 
186      * Constructs a new `LevelFilter`
187      * with the given `Level*`
188      *
189      * Params:
190      *   level = the level address
191      */
192     this(Level* level)
193     {
194         this.level = level;
195     }
196 
197     /** 
198      * Filters the given message according
199      * to the current level. This will no-op
200      * and always return `true` if the message
201      * is not a kind-of `BasicMessage`
202      *
203      * Params:
204      *   message = the message
205      * Returns: the verdict
206      */
207     public bool filter(Message message)
208     {
209         // Only handle BasicMessage(s)
210         BasicMessage bmesg = cast(BasicMessage)message;
211         if(bmesg)
212         {
213             return bmesg.getLevel() <= *this.level;
214         }
215 
216         return true;
217     }
218 }
219 
220 /** 
221  * A basic logger which has support
222  * for log levels
223  */
224 public class BasicLogger : Logger
225 {
226     /** 
227      * The current log level
228      */
229     private Level level;
230 
231     /** 
232      * Constructs a new `BasicLogger`
233      */
234     this()
235     {
236         // Attach a new level-filter
237         // with access to our current
238         // level
239         addFilter(new LevelFilter(&level));
240     }
241 
242     /** 
243      * Sets the log level
244      *
245      * Params:
246      *   level = the new
247      * level
248      */
249     public final void setLevel(Level level)
250     {
251         this.level = level;
252     }
253 
254     /** 
255      * Obtains the current log
256      * level
257      *
258      * Returns: the current level
259      */
260     public final Level getLevel()
261     {
262         return this.level;
263     }
264 }