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             scope(failure) {}
67             string msg = text(args);
68             logger.log(msg, LoggingLevel.Debug);
69         }
70     }
71     
72     /// Not lazy wrapper for multiple args messages
73     void logInfo(E...)(shared ILogger logger, E args)
74     {
75         scope(failure) {}
76         logger.log(text(args), LoggingLevel.Notice);
77     }
78 
79     /// Lazy wrapper for one string message
80     void logInfo()(shared ILogger logger, lazy string message)
81     {
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         scope(failure) {}
89         logger.log(text(args), LoggingLevel.Warning);
90     }
91     
92     /// Lazy wrapper for one string message
93     void logWarning()(shared ILogger logger, lazy string message)
94     {
95         logger.log(message, LoggingLevel.Warning);
96     }
97     
98     /// Not lazy wrapper for multiple args messages
99     void logError(E...)(shared ILogger logger, E args)
100     {
101         scope(failure) {}
102         logger.log(text(args), LoggingLevel.Fatal);
103     }
104     
105     /// Lazy wrapper for one string message
106     void logError()(shared ILogger logger, lazy string message)
107     {
108         logger.log(message, LoggingLevel.Fatal);
109     }
110 }
111     
112 /**
113 *   Interface for lazy logging. Assumes to be nothrow.
114 *   Underlying realization should be concurrent safe.
115 *
116 *   $(B StyleEnum) is enum that used to distinct logging
117 *   levels and define ordering for verbosity muting.
118 */
119 shared interface IStyledLogger(StyleEnum)
120 {
121     /**
122     *   Setting new log file name. If the $(B value)
123     *   differs from old one, logger should close
124     *   old one and open new file.
125     */
126     void name(string value) @property;
127     
128     nothrow 
129     {
130         /**
131         *   Log file name.
132         */
133         string name() @property const;
134         
135         /**
136         *   Prints message into log. Displaying in the console
137         *   controlled by minOutputLevel property.
138         */
139         void log(lazy string message, StyleEnum level);
140 
141         /**
142         *   Returns: minimum log level,  will be printed in the console.
143         */
144         StyleEnum minOutputLevel() const @property;
145 
146         /**
147         *   Setups minimum message level that goes to console.
148         */
149         void minOutputLevel(StyleEnum level) @property;
150         
151         /**
152         *   Setups minimum message level that goes to file.
153         */
154         StyleEnum minLoggingLevel() @property;
155         
156         /**
157         *   Setups minimum message level that goes to file.
158         */
159         void minLoggingLevel(StyleEnum level) @property;
160         
161         /**
162         *   Used to manual shutdown protocols.
163         */
164         void finalize();
165     }
166 
167     /**
168     *   Unsafe write down the message without any meta information.
169     */
170     void rawInput(string message);
171     
172     /**
173     *   Format message with default logging style (etc. time and level string).
174     */
175     string formatConsoleOutput(string message, StyleEnum level);
176     
177     /**
178     *   Format message with default logging style (etc. time and level string).
179     */
180     string formatFileOutput(string message, StyleEnum level);
181     
182     /**
183     *   Checks if the log file is exists at specified $(B location) and
184     *   if can't find it, recreates the file and continues write into it.
185     *
186     *   Useful for $(B logrotate) utility. GNU/Linux system checks file identity by
187     *   inode, that doesn't change while renaming. Thus after renaming the file at 
188     *   $(B location) log continues write into the renamed file. The call to the
189     *   $(B reload) method force splitting log into two parts.
190     *
191     *   Note: The method is not nothrow!
192     */
193     void reload();
194 }