root/trunk/tango/scrapple/io/Logout.d

Revision 10, 19.0 kB (checked in by flithm, 1 year ago)

reorganize, close a bunch of tickets

Line 
1 /*******************************************************************************
2
3         Copyright:      Copyright (c) 2007 Tim Burrell. All rights reserved.
4
5         License:        BSD style: $(LICENSE)
6
7         Version:        Aug 29 2007: Initial release
8
9         Author:         Tim Burrell [tim <dot> burrell <at> gmail <dot> com]
10         
11         Logging module for quick and easy logging to console and log files
12
13 *******************************************************************************/
14
15 module  tango.scrapple.io.Logout;
16
17 import  tango.io.FilePath;
18 import  tango.io.Stdout;
19 import  tango.util.log.ConsoleAppender;
20 import  tango.util.log.RollingFileAppender;
21 import  tango.util.log.DateLayout;
22 import  tango.util.log.EventLayout;
23 import  tango.util.log.Log;
24 import  tango.util.log.Logger;
25 import  tango.util.log.Event;
26 import  tango.util.log.EventLayout;
27
28 ////////////////////////////////////////////////////////////////////////////
29 // Typedef's / Enums
30 ///////////////////////////////////////
31
32 /*******************************************************************************
33  
34   LoggingLevel states that define how much output gets printed / logged
35  
36   Valid Levels are as follows:
37   ---
38   TraceTrivial
39   TraceDebug
40   Trace
41   Info
42   Warn
43   Error
44   Fatal
45   Quiet
46   ---
47  
48 *******************************************************************************/
49
50 enum LoggingLevel {
51         TraceTrivial,
52         TraceDebug,
53         Trace,
54         Info,
55         Warn,
56         Error,
57         Fatal,
58         Quiet,
59 }
60
61 ////////////////////////////////////////////////////////////////////////////
62 // Logging Definition
63 ///////////////////////////////////////
64
65 /*******************************************************************************
66
67   The Logging class wraps the tango logging API into a package that provides
68   some useful default behavior that may be suitable for easy inclusion into
69   projects that want quick and easy access to file / console logging, with
70   a minimum amount of hassle.
71  
72   The default behavior is to log data to both the console and a file if a
73   custom log name is set with Logging.logger.  If no logger is set then
74   (by default) data will only be output to the console.
75  
76   The Logging class also provides some additional output levels beyond
77   the ones provided by Tango's logging API, for additional control.
78  
79   The output routines are lazily evaulated so if the current output
80   verbosity is higher than the data being outputted there is a relatively
81   low amount of overhead.
82  
83   Examples:
84  
85   In order to use the Logging class you can use the globally instantiated
86   Logout object.  All you need to do is (optionally) first set the log name:
87   ---
88   Logout.logger = "LogName"
89   ---
90   This will create "LogNameX.log" where X is a number.  The default file log
91   format is to use RollingFileAppender so that the log files do not get too
92   large on disk.  There will only ever be a maximum of two 1 MB log files
93   created by default.
94  
95   In order to set the current logging level use the following methods:
96   ---
97   Logout.level = LoggingLevel.TraceDebug;
98   ---
99   This will set the logging level to TraceDebug.  Note that the default level
100   is LoggingLevel.info.
101  
102   In order to actually produce some log output the following can be done:
103   ---
104   Logout("test");                      // Log text using the default output level (Info)
105   Logout.trivial("test");              // Log text using the TraceTrivial output level
106   Logout.dbg("test");                  // Log text using the TraceDebug output level
107   Logout.trace("test");                // Log text using the Trace output level
108   Logout.info("test");                 // Log text using the Info output level
109   Logout.warn("test");                 // Log text using the Warn output level
110   Logout.error("test");                // Log text using the Error output level
111   Logout.fatal("test");                // Log text using the Fatal output level
112   ---
113   Text can also be formatted using the Logging class:
114   ---
115   Logout.format("test {0}", var);      // Log text using the default output level (Info)
116   Logout.dbg.format("test {0}", var);  // Log text using the TraceTrivial output level
117   ---
118  
119 *******************************************************************************/
120
121 class Logging
122 {
123         ////////////////////////////////////////////////////////////////////
124         // Constants
125         ///////////////////////////////
126        
127         const ubyte             DEFAULT_NUM_FILE_LOGS = 2;              /// Default number of logs to rotate between
128         const ulong             DEFAULT_LOG_SIZE = 1024;                /// Default size of each log
129         const char []           DEFAULT_LOGGER_NAME = "DefaultLogger";  /// Default logger name
130        
131         ////////////////////////////////////////////////////////////////////
132         // Public members
133         ///////////////////////////////
134        
135         public alias  log        opCall;                                /// Alias opCall
136        
137         ////////////////////////////////////////////////////////////////////
138         // Construction
139         ///////////////////////////////
140        
141         /**
142          * Default Constructor
143         **/
144         this () {
145                 mNumFileLogs = DEFAULT_NUM_FILE_LOGS;
146                 mLastLevel = LoggingLevel.Info;
147                 mLogPath = null;
148                 mLogSize = DEFAULT_LOG_SIZE * 1024;
149                 layoutConsole = new LoggingConsoleLayout();
150                 layoutFile = new LoggingFileLayout();
151                 logger(DEFAULT_LOGGER_NAME, true, false);
152                 level(LoggingLevel.Info);
153         }
154        
155         /**
156          * Destructor
157         **/
158         ~this () {
159         }
160        
161         ////////////////////////////////////////////////////////////////////
162         // Public Functions
163         ///////////////////////////////
164        
165         /**
166          * Format a string and output via the logger
167          *
168          * Params:         Fmt =           Formatting string
169          *                 ... =           Parameters
170          * Returns:                        Self
171         **/
172         final Logging format(lazy char [] Fmt, ...) {
173                 return log(Stdout.layout().convert(_arguments, _argptr, Fmt));
174         }
175        
176         /**
177          * Set the console output layout
178          *
179          * Params:        ConsoleLayout =  Set the layout of the console output
180         **/
181         void layoutConsole(LoggingConsoleLayout LayoutConsole) {
182                 mLayoutConsole = LayoutConsole;
183         }
184        
185         /**
186          * Set the file output layout
187          *
188          * Params:        FileLayout =     Set the layout of the file output
189         **/
190         void layoutFile(LoggingFileLayout LayoutFile) {
191                 mLayoutFile = LayoutFile;
192         }
193        
194         /**
195          * Set the logger name
196          *
197          * Params:        LogLevel =       Set the level of the logger
198          * Returns:                        Current level of the logging class
199         **/
200         LoggingLevel level(LoggingLevel LogLevel) {
201                 mLevel = LogLevel;
202                 mLogger.setLevel(convertLevel(LogLevel));
203                 return level();
204         }
205        
206         /**
207          * Get the logger name
208          *
209          * Returns:                        Current level of the logging class
210         **/
211         LoggingLevel level() {
212                 return mLevel;
213         }
214        
215         /**
216          * Log some text
217          *
218          * Params:        Output =         Text to log
219         **/
220         final Logging log(lazy char [] Output) {
221                 return log(Output, mLastLevel);
222         }
223        
224         /**
225          * Log some text
226          *
227          * Params:        LogLevel =       Level of output
228          *                Output =         Text to log
229          * Returns:                        Self
230         **/
231         final Logging log(lazy char [] Output, LoggingLevel LogLevel) {
232                 mLastLevel = LogLevel;
233                 // evaluate Output last so lazy can avoid processing it if there's
234                 // no need!
235                 if ((LogLevel >= mLevel) && Output)
236                         mLogger.append(convertLevel(LogLevel), Output);
237                 return this;
238         }
239        
240         /**
241          * Set the logger name
242          *
243          * Params:        LoggerName =     Name of the logger
244          *                ConsoleOutput =  Should output go to the console?
245          *                FileOutput =     Should output go to the log files?
246          *                LogPath =        Path to log file
247          * Returns:                        Logger name
248         **/
249         char [] logger(char [] LoggerName, bool ConsoleOutput = true, bool FileOutput = true, char [] LogPath = null) {
250                 mConsoleOutput = ConsoleOutput;
251                 mFileOutput = FileOutput;
252                 mLogger = Log.getLogger(LoggerName);
253                 mLogger.clearAppenders();
254                 mLogPath = LogPath;
255                 if (ConsoleOutput)
256                         mLogger.addAppender(new ConsoleAppender(mLayoutConsole));
257                 if (FileOutput)
258                         if (mLogPath is null)
259                                 mLogger.addAppender(new RollingFileAppender(LoggerName ~ ".log", mNumFileLogs, mLogSize, mLayoutFile));
260                         else {
261                                 FilePath dir = new FilePath(mLogPath);
262                                 try {
263                                         dir.create();
264                                         mLogger.addAppender(new RollingFileAppender(mLogPath ~ "/" ~ LoggerName ~ ".log", mNumFileLogs, mLogSize, mLayoutFile));
265                                 } catch (Exception e) {
266                                         warn.format("Unable to create logfile [{0}/{1}.log]", mLogPath, LoggerName);
267                                 }
268                         }
269                 return logger();
270         }
271        
272         /**
273          * Get the logger name
274          *
275          * Returns:                        Name of the logger
276         **/
277         char [] logger() {
278                 return mLogger.name;
279         }
280        
281         /**
282          * Set the logfile path
283          *
284          * Send null (or no parameter) to remove the log path
285          *
286          * Params:        Path =           Directory that will contain the log file
287         **/
288         void logPath(char [] Path = null) {
289                 mLogPath = Path;
290                 logger(mLogger.name, mConsoleOutput, mFileOutput);
291         }
292        
293         /**
294          * Output a newline
295          *
296          * Params:        Output =         Text to output
297          * Returns:                        Self
298         **/
299         final Logging newline() {
300                 mLayoutFile.SkipNextHeader = true;
301                        return log("", mLastLevel);
302         }
303        
304         /**
305          * Output data using the Debug.Trivial setting
306          *
307          * Params:        Output =         Text to output
308          * Returns:                        Self
309         **/
310         final Logging trivial(lazy char [] Output = null) {
311                 return log(Output, LoggingLevel.TraceTrivial);
312         }
313                
314         /**
315          * Output data using the Debug.Trace setting
316          *
317          * Params:        Output =         Text to output
318          * Returns:                        Self
319         **/
320         final Logging dbg(lazy char [] Output = null) {
321                 return log(Output, LoggingLevel.TraceDebug);
322         }
323        
324         /**
325          * Output data using the Debug setting
326          *
327          * Params:        Output =         Text to output
328          * Returns:                        Self
329         **/
330         final Logging trace(lazy char [] Output = null) {
331                 return log(Output, LoggingLevel.Trace);
332         }
333        
334         /**
335          * Output data using the Info setting
336          *
337          * Params:        Output =         Text to output
338          * Returns:                        Self
339         **/
340         final Logging info(lazy char [] Output = null) {
341                 return log(Output, LoggingLevel.Info);
342         }
343        
344         /**
345          * Output data using the Warn setting
346          *
347          * Params:        Output =         Text to output
348          * Returns:                        Self
349         **/
350         final Logging warn(lazy char [] Output = null) {
351                 return log(Output, LoggingLevel.Warn);
352         }
353        
354         /**
355          * Output data using the Error setting
356          *
357          * Params:        Output =         Text to output
358          * Returns:                        Self
359         **/
360         final Logging error(lazy char [] Output = null) {
361                 return log(Output, LoggingLevel.Error);
362         }
363        
364         /**
365          * Output data using the Fatal setting
366          *
367          * Params:        Output =         Text to output
368          * Returns:                        Self
369         **/
370         final Logging fatal(lazy char [] Output = null) {
371                 return log(Output, LoggingLevel.Fatal);
372         }
373        
374         ////////////////////////////////////////////////////////////////////
375        
376 private:
377        
378         ////////////////////////////////////////////////////////////////////
379         // Private Functions
380         ///////////////////////////////       
381        
382         /**
383          * Convert LoggingLevel to Logger.Level
384          *
385          *
386          * Params:        Level =          Logging.Level
387          * Returns:                        Logger.Level
388         **/
389         Logger.Level convertLevel(LoggingLevel Level) {
390                 switch (Level) {
391                 case LoggingLevel.TraceTrivial:
392                 case LoggingLevel.TraceDebug:
393                 case LoggingLevel.Trace:
394                         return Logger.Level.Trace;
395                 default:
396                 case LoggingLevel.Info:
397                         return Logger.Level.Info;
398                 case LoggingLevel.Warn:
399                         return Logger.Level.Warn;
400                 case LoggingLevel.Error:
401                         return Logger.Level.Error;
402                 case LoggingLevel.Fatal:
403                         return Logger.Level.Fatal;
404                 case LoggingLevel.Quiet:
405                         return Logger.Level.None;
406                 }
407                 return Logger.Level.Info;
408         }
409        
410         ////////////////////////////////////////////////////////////////////
411         // Private Members
412         ///////////////////////////////       
413        
414         bool                    mConsoleOutput;                         /// Write to the console?
415         bool                    mFileOutput;                            /// Write to logfile?
416         LoggingLevel            mLastLevel;                             /// LoggingLevel of last output
417         LoggingLevel            mLevel;                                 /// Debugging level
418         Logger                  mLogger;                                /// Is the thing constructed?
419         char []                 mLogPath;                               /// Path of the log file
420         LoggingConsoleLayout    mLayoutConsole;                         /// The log output console format
421         LoggingFileLayout       mLayoutFile;                            /// The log output file format
422         ulong                   mLogSize;                               /// Size in KB of each log
423         ubyte                   mNumFileLogs;                           /// Number of file logs to rotate between
424 }
425
426 ////////////////////////////////////////////////////////////////////////////
427 // LoggingLayout
428 ///////////////////////////////////////
429
430 /*******************************************************************************
431
432   LoggingConsoleLayout Class
433  
434   This is the default layout for Console output.
435  
436   If you want to change this layout simply create a new class
437   that inherits this one and pass it in using:
438   ---
439   Logout.layoutConsole = NewLayout;
440   ---
441   See the tango <a href="http://www.dsource.org/projects/tango/docs/current/tango.util.log.EventLayout.html">EventLayout docs</a> for more information on this
442  
443 *******************************************************************************/
444
445 class LoggingConsoleLayout : EventLayout
446 {
447         ////////////////////////////////////////////////////////////////////
448         // Public Functions
449         ///////////////////////////////
450        
451         /**
452          * Set the layout header
453          *
454          * Params:        Event =          The log event
455          * Returns:                        The formatted header
456         **/
457         char[] header(Event Event) {
458                 switch (Event.getLevel()) {
459                 case Logger.Level.Trace:
460                 default:
461                 case Logger.Level.Info:
462                 break;
463                 case Logger.Level.Warn:
464                 case Logger.Level.Error:
465                         Event.append(Event.getLevelName()).append(" - ");
466                         break;
467                 case Logger.Level.Fatal:
468                         Event.append("FATAL - ");
469                         break;
470                 }
471                
472                 return Event.getContent();
473         }
474 }
475
476 /*******************************************************************************
477
478   LoggingFileLayout Class
479  
480   This is the default layout for File output.
481  
482   If you want to change this layout simply create a new class
483   that inherits this one and pass it in using:
484   ---
485   Logout.layoutFile = NewLayout;
486   ---
487   See the tango <a href="http://www.dsource.org/projects/tango/docs/current/tango.util.log.EventLayout.html">EventLayout docs</a> for more information on this
488  
489 *******************************************************************************/
490
491 class LoggingFileLayout : DateLayout
492 {
493         ////////////////////////////////////////////////////////////////////
494         // Public members
495         ///////////////////////////////
496        
497         bool                    SkipNextHeader;                         /// Skip the next header output?
498        
499         ////////////////////////////////////////////////////////////////////
500         // Construction
501         ///////////////////////////////
502        
503         /**
504          * Default Constructor
505         **/
506         this() {
507                 SkipNextHeader = false;
508         }
509        
510         ////////////////////////////////////////////////////////////////////
511         // Public Functions
512         ///////////////////////////////
513        
514         /**
515          * Set the layout header
516          *
517          * Params:        Event =          The log event
518          * Returns:                        The formatted header
519         **/
520         char[] header(Event Event) {
521                 if (SkipNextHeader)
522                         SkipNextHeader = false;
523                 else
524                         Event.append(super.header(Event));
525                
526                 return Event.getContent();
527         }
528 }
529
530 ////////////////////////////////////////////////////////////////////////////
531 // Globals
532 ///////////////////////////////////////
533
534 static this() {
535         Logout = new Logging();
536 }
537
538 public static Logging Logout;                                           /// Global Logout object
Note: See TracBrowser for help on using the browser.