1 /**
2 *    Logging system designed to operate in concurrent application.
3 *
4 *    The system should be initialized with $(B initLoggingSystem) function.
5 *    There is no need to call shutdown function as it is happen in module
6 *    destructor.
7 *
8 *    Example:
9 *    ---------
10 *    void testThread()
11 *    {
12 *        foreach(j; 1 .. 50)
13 *        {
14 *            logInfo(to!string(j));
15 *            logError(to!string(j));
16 *        }
17 *    }    
18 *
19 *    foreach(i; 1 .. 50)
20 *    {
21 *        spawn(&testThread);
22 *    }
23 *    ---------
24 *
25 *   Copyright: © 2013-2014 Anton Gushcha
26 *   License: Subject to the terms of the MIT license, as written in the included LICENSE file.
27 *   Authors: NCrashed <ncrashed@gmail.com>
28 *
29 */
30 module dlogg.log;
31 @safe:
32 
33 public import std.conv;
34 
35 /**
36 *   Log levels defines style of the messages.
37 *   Printing in console can be controlled by
38 *   ILogger.minOutputLevel property.
39 */
40 enum LoggingLevel
41 {
42     Notice,
43     Warning,
44     Debug,
45     Fatal,
46     Muted // Used only to mute all writing to console
47 }
48 
49 /**
50 *   Default logger interface that uses $(B LoggingLevel) as
51 *   enum that describes ordering of logging levels.
52 */
53 alias ILogger = IStyledLogger!(LoggingLevel);
54 
55 // wrappers for easy logging
56 nothrow @trusted
57 {
58     /**
59     *   Wrapper for handy debug messages.
60     *   Warning: main purpose for debug messages, thus it is not lazy.
61     */
62     void logDebug(E...)(shared ILogger logger, E args)
63     {
64         debug
65         {
66             try logger.log(text(args), LoggingLevel.Debug);
67             catch(Exception e) {}
68         }
69     }
70     
71     /// Not lazy wrapper for multiple args messages
72     void logInfo(E...)(shared ILogger logger, E args)
73     {
74         try logger.log(text(args), LoggingLevel.Notice);
75         catch(Exception e) {}
76     }
77 
78     /// Lazy wrapper for one string message
79     void logInfo()(shared ILogger logger, lazy string message)
80     {
81         if(message is null) return;
82         logger.log(message, LoggingLevel.Notice);
83     }
84     
85     /// Not lazy wrapper for multiple args messages
86     void logWarning(E...)(shared ILogger logger, E args)
87     {
88         try logger.log(text(args), LoggingLevel.Warning);
89         catch(Exception e) {}
90     }
91     
92     /// Lazy wrapper for one string message
93     void logWarning()(shared ILogger logger, lazy string message)
94     {
95         if(message is null) return;
96         logger.log(message, LoggingLevel.Warning);
97     }
98     
99     /// Not lazy wrapper for multiple args messages
100     void logError(E...)(shared ILogger logger, E args)
101     {
102         try logger.log(text(args), LoggingLevel.Fatal);
103         catch(Exception e) {}
104     }
105     
106     /// Lazy wrapper for one string message
107     void logError()(shared ILogger logger, lazy string message)
108     {
109         if(message is null) return;
110         logger.log(message, LoggingLevel.Fatal);
111     }
112 }
113     
114 /**
115 *   Interface for lazy logging. Assumes to be nothrow.
116 *   Underlying realization should be concurrent safe.
117 *
118 *   $(B StyleEnum) is enum that used to distinct logging
119 *   levels and define ordering for verbosity muting.
120 */
121 shared interface IStyledLogger(StyleEnum)
122 {
123     /**
124     *   Setting new log file name. If the $(B value)
125     *   differs from old one, logger should close
126     *   old one and open new file.
127     */
128     void name(string value) @property;
129     
130     nothrow 
131     {
132         /**
133         *   Log file name.
134         */
135         string name() @property const;
136         
137         /**
138         *   Prints message into log. Displaying in the console
139         *   controlled by minOutputLevel property.
140         */
141         void log(lazy string message, StyleEnum level);
142 
143         /**
144         *   Returns: minimum log level,  will be printed in the console.
145         */
146         StyleEnum minOutputLevel() const @property;
147 
148         /**
149         *   Setups minimum message level that goes to console.
150         */
151         void minOutputLevel(StyleEnum level) @property;
152         
153         /**
154         *   Setups minimum message level that goes to file.
155         */
156         StyleEnum minLoggingLevel() @property;
157         
158         /**
159         *   Setups minimum message level that goes to file.
160         */
161         void minLoggingLevel(StyleEnum level) @property;
162         
163         /**
164         *   Used to manual shutdown protocols.
165         */
166         void finalize();
167     }
168 
169     /**
170     *   Unsafe write down the message without any meta information.
171     */
172     void rawInput(string message);
173     
174     /**
175     *   Format message with default logging style (etc. time and level string).
176     */
177     string formatConsoleOutput(string message, StyleEnum level);
178     
179     /**
180     *   Format message with default logging style (etc. time and level string).
181     */
182     string formatFileOutput(string message, StyleEnum level);
183     
184     /**
185     *   Checks if the log file is exists at specified $(B location) and
186     *   if can't find it, recreates the file and continues write into it.
187     *
188     *   Useful for $(B logrotate) utility. GNU/Linux system checks file identity by
189     *   inode, that doesn't change while renaming. Thus after renaming the file at 
190     *   $(B location) log continues write into the renamed file. The call to the
191     *   $(B reload) method force splitting log into two parts.
192     *
193     *   Note: The method is not nothrow!
194     */
195     void reload();
196 }