Merge branch 'master' of ssh://feistymeow.org/feisty_meow
[feisty_meow.git] / nucleus / library / loggers / file_logger.h
1 #ifndef FILE_LOGGER_CLASS
2 #define FILE_LOGGER_CLASS
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : file_logger                                                       *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 //! Enables the printing of information to a log file.
19 /*!
20   The information can be conditionally printed using the filter support.
21   The log file will automatically be truncated when it passes the size limit.
22 */
23
24 #include "console_logger.h"
25 #include "eol_aware.h"
26 #include "filter_set.h"
27
28 #include <basis/astring.h>
29 #include <basis/contracts.h>
30 #include <basis/functions.h>
31 #include <basis/mutex.h>
32 #include <filesystem/byte_filer.h>
33 #include <textual/parser_bits.h>
34
35 namespace loggers {
36
37 class file_logger : public virtual standard_log_base
38 {
39 public:
40   file_logger();
41     //!< creates a logger without a log file and with the default size limit.
42     /*!< the log file name can be changed using filename(). */
43
44   file_logger(const basis::astring &filename, int limit = DEFAULT_LOG_FILE_SIZE);
45     //!< constructs a logger using the "filename" for output.
46     /*!< there will be no logging if the "filename" is empty.  the "limit"
47     specifies how large the log file can be (in bytes). */
48
49   virtual ~file_logger();
50
51   DEFINE_CLASS_NAME("file_logger");
52
53   enum limits {
54     //! this just defines the default for the log file size.
55     DEFAULT_LOG_FILE_SIZE = 0x10F00D
56   };
57
58   bool good() const;
59     //!< returns true if the logger appears correctly hooked up to a file.
60     /*!< note that we don't open the file when file_logger is constructed;
61     it is only opened once the first logging is attempted. */
62
63   bool reopen();
64     //!< closes the current file and attempts to reopen it.
65     /*!< this is handy if the original opening of the file failed. */
66
67   basis::outcome log(const basis::base_string &info, int filter = basis::ALWAYS_PRINT);
68     //!< writes information to the log file (if the filename is valid).
69     /*!< the "filter" value is checked to see if it is in the current set
70     of allowed filters.  a value of zero is always printed.  if the filename()
71     has not been set, then the information is lost. */
72
73   basis::outcome log_bytes(const basis::byte_array &to_log, int filter = basis::ALWAYS_PRINT);
74     //!< sends a stream of bytes "to_log" without interpretation into the log.
75     /*!< if the "filter" is not enabled, then the info is just tossed out. */
76
77   basis::outcome format_bytes(const basis::byte_array &to_log, int filter = basis::ALWAYS_PRINT);
78     //!< fancifully formats a stream of bytes "to_log" and sends them into log.
79
80   basis::astring name() const;
81     //!< observes the filename where logged information is written.
82   void name(const basis::astring &new_name);
83     //!< modifies the filename where logged information will be written.
84     /*!< if "new_name" is blank, then the logged information will not
85     be saved. */
86
87   int limit() const { return int(_file_limit); }
88     //!< observes the allowable size of the log file.
89   void limit(int new_limit) { _file_limit = new_limit; }
90     //!< modifies the allowable size of the log file.
91
92   void flush();
93     //!< causes any pending writes to be sent to the output file.
94
95   void truncate(size_t new_size);
96     //!< chops the file to ensure it doesn't go much over the file size limit.
97     /*!< this can be used externally also, but be careful with it. */
98
99   //! returns a log file name for file_logger based on the program name.
100   /*! for a program named myapp.exe, this will be in the form:
101     {logging_dir}/myapp.log
102   */
103   static basis::astring log_file_for_app_name();
104
105 private:
106   basis::astring *_filename;  //!< debugging output file.
107   size_t _file_limit;  //!< maximum length of file before truncation.
108   filesystem::byte_filer *_outfile;  //!< the object that points at our output file.
109   basis::mutex *_flock;  //!< protects the file and other parameters.
110
111   int size_reduction() const;
112     //!< returns the size of the chunk to truncate from the file.
113     /*!< this is a percentage of the maximum size allowed. */
114
115   bool open_file();
116     //!< if the opening of the file is successful, then true is returned.
117     /*!< also, the _outfile member variable is non-zero. */
118
119   void close_file();
120     //!< shuts down the file, if any, we had opened for logging.
121
122   // unavailable.
123   file_logger(const file_logger &);
124   file_logger &operator =(const file_logger &);
125 };
126
127 //////////////
128
129 //! a macro that retasks the program-wide logger as a file_logger.
130 #define SETUP_FILE_LOGGER { \
131   loggers::standard_log_base *old_log = loggers::program_wide_logger::set \
132     (new loggers::file_logger(loggers::file_logger::log_file_for_app_name())); \
133   WHACK(old_log); \
134 }
135
136 } //namespace.
137
138 #endif
139