1 module log;
2 
3 import std.stdio;
4 
5 alias trace = log!(Level.trace);
6 alias info = log!(Level.info);
7 alias warn = log!(Level.warn);
8 alias error = log!(Level.error);
9 alias fatal = log!(Level.fatal);
10 
11 template log(Level level)
12 {
13     void log(string fmt, string file = __FILE__, size_t line = __LINE__, A...)(lazy A args)
14     {
15         import std.format : format;
16 
17         if (level & levels)
18             logger.log(level, file, line, format!fmt(args));
19     }
20 }
21 
22 static this()
23 {
24     logger = Logger(stderr);
25     levels = Level.info | Level.warn | Level.error | Level.fatal;
26 }
27 
28 Logger logger;
29 
30 struct Logger
31 {
32     private File file;
33 
34     this(File file)
35     {
36         this.file = file;
37     }
38 
39     void log(Level level, string file, size_t line, string message) @safe
40     {
41         import std.conv : to;
42 
43         auto writer = this.file.lockingTextWriter;
44 
45         writer.put(level.to!string);
46         writer.put(": ");
47         writer.put(message);
48         writer.put('\n');
49     }
50 }
51 
52 uint levels;
53 
54 enum Level
55 {
56     trace = 1, // detailed tracing
57     info = 2, // useful information
58     warn = 4, // potential problem
59     error = 8, // recoverable error
60     fatal = 16, // fatal failure
61 }