KISSCPP
a C++ library for rapid application development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
logstream.hpp
Go to the documentation of this file.
1 // File : logstream.hpp
2 // Author: Dirk J. Botha <bothadj@gmail.com>
3 //
4 // This file is part of kisscpp library.
5 //
6 // The kisscpp library is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // The kisscpp library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with the kisscpp library. If not, see <http://www.gnu.org/licenses/>.
18 
19 #ifndef _LOGSTREAM_HPP_
20 #define _LOGSTREAM_HPP_
21 
22 #include <sstream>
23 #include <fstream>
24 #include <stdint.h>
25 #include <iostream>
26 #include <stdexcept>
27 #include <deque>
28 #include <boost/thread/mutex.hpp>
29 #include <boost/thread/locks.hpp>
30 #include <boost/date_time/posix_time/posix_time.hpp>
31 #include <boost/algorithm/string.hpp>
32 
33 #define DEFAULT_MAX_BUFF_SIZE 5000
34 
35 namespace kisscpp
36 {
37  //--------------------------------------------------------------------------------
39  enum log_type {
40  LT_DEBUG = 0,
41  LT_INFO = 1,
42  LT_ERROR = 2
43  };
44 
46  enum log_severity {
47  LS_LOW = 0,
48  LS_NORMAL = 1,
49  LS_HIGH = 2
50  };
51 
52  //--------------------------------------------------------------------------------
53  class LogStream;
54 
55  #pragma GCC visibility push(default)
56 
57  template<typename T> class ManipResult;
58 
59  //--------------------------------------------------------------------------------
60  // Free functions which manipulate the stream. Similar to standard C++ stream manipulators.
61  namespace manip
62  {
63  // ------------------------------------
64  // LogStream Manipulators (no parameters)
66  LogStream& endl (LogStream& s);
67  LogStream& dec (LogStream& s);
68  LogStream& hex (LogStream& s);
69  LogStream& oct (LogStream& s);
70  LogStream& base (LogStream& s);
71 
72  LogStream& error (LogStream& s, const bool permanent = false);
73  LogStream& info (LogStream& s, const bool permanent = false);
74  LogStream& debug (LogStream& s, const bool permanent = false);
75 
76  LogStream& high (LogStream& s, const bool permanent = false);
77  LogStream& normal (LogStream& s, const bool permanent = false);
78  LogStream& low (LogStream& s, const bool permanent = false);
79 
80  LogStream& error_high (LogStream& s, const bool permanent = false);
81  LogStream& error_normal(LogStream& s, const bool permanent = false);
82  LogStream& error_low (LogStream& s, const bool permanent = false);
83  LogStream& debug_high (LogStream& s, const bool permanent = false);
84  LogStream& debug_normal(LogStream& s, const bool permanent = false);
85  LogStream& debug_low (LogStream& s, const bool permanent = false);
86  LogStream& info_high (LogStream& s, const bool permanent = false);
87  LogStream& info_normal (LogStream& s, const bool permanent = false);
88  LogStream& info_low (LogStream& s, const bool permanent = false);
89 
90  //--------------------------------------------------------------------------
91  // Stream manipulators (with parameters)
92  //
93  // ManipResult is the type passed into operator<< because manipulators that take parameters are function calls, as opposed to the name of a function pointer type, as in the case of the no-parameter manipulators.
94  // -------------------------------------------------------------------------
95 
96  namespace helpers
97  {
98  LogStream& ent (LogStream& s, std::string ent_name);
99  LogStream& source(LogStream& s, std::string source );
100  }
101 
102  ManipResult<std::string> ent (const std::string& ent_name);
103  ManipResult<std::string> src (const std::string& source );
104 
105  } // manip
106 
107  using namespace manip;
108 
109  //--------------------------------------------------------------------------------
110  // Internally-used class to temporarily store settings changed by the stream manipulators.
112  {
113  public:
114  LogStreamSettings() : messageType(LT_INFO), severity(LS_NORMAL), entityName(""), source("") {}
115 
117  {
118  if(&lss != this) {
119  messageType = lss.getMessageType();
120  severity = lss.getSeverity();
121  entityName = lss.getEntityName();
122  source = lss.getSource();
123  }
124  return *this;
125  }
126 
127  log_type getMessageType() const throw() { return messageType; }
128  log_severity getSeverity () const throw() { return severity; }
129  const std::string& getEntityName () const throw() { return entityName; }
130  const std::string& getSource () const throw() { return source; }
131 
132  void setMessageType(log_type mt) { messageType = mt;}
133  void setSeverity (log_severity ms) { severity = ms;}
134  void setEntityName (const std::string &en) { entityName = en;}
135  void setSource (const std::string &s ) { source = s ;}
136 
137  private:
138  log_type messageType;
139  log_severity severity;
140  std::string entityName;
141  std::string source; // The source of the log message.
142  };
143 
144  //--------------------------------------------------------------------------------
145  class LogStream
146  {
147  public:
148  typedef LogStream& (*manip_func) (LogStream&); // LogStream manipulator function which is passed to operator<< without any arguments (other than the implicit %LogStream).
149  typedef LogStream& (*manip_func1) (LogStream&, const bool permanent); // LogStream manipulator function which is passed to operator<< with a single boolean argument.
150  // The boolean is called with `false` from within operator<<, and `true` from the constructor.
151  // constructors
152  // ------------
153  explicit
154  LogStream(manip_func1 manip = info_normal)
155  {
156  manip(*this, false);
157  lssTemp = lssPerm;
158  doFlush = false;
159  }
160 
161  // ------------
162  LogStream(manip_func1 manip, const std::string &src)
163  {
164  lssTemp = lssPerm;
165  doFlush = false;
166  manip(*this, false);
167  setSource(src);
168  }
169 
170  // ------------
171  LogStream(const std::string &src)
172  {
173  lssTemp = lssPerm;
174  doFlush = false;
175  info_normal(*this, false);
176  setSource(src);
177  start_write();
178  }
179 
180  // ------------
181  LogStream(const std::string &src,
182  const std::string &path,
183  const bool log2console = false,
184  const unsigned int i = DEFAULT_MAX_BUFF_SIZE)
185  {
186  lssTemp = lssPerm;
187  doFlush = false;
188  info_normal(*this, true);
189  setSource(src);
190  log2consoleFlag = log2console;
191  outFilePath = path;
192  maxBufferSize = i;
193  start_write();
194  }
195 
197  {
198  lssTemp = o.lssTemp;
199  doFlush = false;
200  maxBufferSize = o.maxBufferSize;
201  start_write();
202  }
203 
205  {
206  end_write();
207  if(mBuf.tellp() > 0) { flush(); }
208  };
209 
211  {
212  if(&o != this) {
213  lssTemp = o.lssTemp;
214  maxBufferSize = o.maxBufferSize;
215  }
216  return *this;
217  }
218 
219  // Output operator for manipulators
220  LogStream& operator<< (manip_func1 f) { return f(*this, false); }; // with one argument (other than the implicit LogStream).
221  LogStream& operator<< (manip_func f) { return f(*this); }; // with no arguments (other than the implicit LogStream).
222 
223  LogStream& operator<< (const std::string& v) { mBuf << v ; return *this; }
224  LogStream& operator<< (const char v) { mBuf << static_cast<short>(v); return *this; }
225  LogStream& operator<< (const short v) { mBuf << v ; return *this; }
226  LogStream& operator<< (const int v) { mBuf << v ; return *this; }
227  LogStream& operator<< (const long v) { mBuf << v ; return *this; }
228  LogStream& operator<< (const float v) { mBuf << v ; return *this; }
229  LogStream& operator<< (const double v) { mBuf << v ; return *this; }
230  LogStream& operator<< (const long double v) { mBuf << v ; return *this; }
231  LogStream& operator<< (const u_char v) { mBuf << static_cast<u_short>(v); return *this; }
232  LogStream& operator<< (const u_short v) { mBuf << v ; return *this; }
233  LogStream& operator<< (const u_int v) { mBuf << v ; return *this; }
234  LogStream& operator<< (const u_long v) { mBuf << v ; return *this; }
235  LogStream& operator<< (const unsigned long long v) { mBuf << v ; return *this; }
236 
237  LogStream& flush() { do_write(true); return *this; }; // Forced Flush buffer to log, empties buffer and stringPool.
238  LogStream& endl () { do_write(false); return *this; }; // Suggested Flush buffer to log, empties mBuf into stringPool
239 
240  // Print numbers in
241  LogStream& dec () { mBuf << std::dec; return *this; }; // decimal.
242  LogStream& hex () { mBuf << std::hex; return *this; }; // hex.
243  LogStream& oct () { mBuf << std::oct; return *this; }; // octal.
244 
245  LogStream& base () { mBuf << std::showbase; return *this; }; // Show the base when printing numbers.
246 
247  // getter methods
248  log_type getMessageType () const throw() { return lssPerm.getMessageType(); }
249  log_severity getSeverity () const throw() { return lssPerm.getSeverity(); }
250  const std::string& getEntityName () const throw() { if(!lssTemp.getEntityName().empty()) return lssTemp.getEntityName(); else return lssPerm.getEntityName(); }
251  const std::string& getSource () const throw() { if(!lssTemp.getSource ().empty()) return lssTemp.getSource(); else return lssPerm.getSource(); }
252  LogStreamSettings& getPermSettings() { return lssTemp; }
253  LogStreamSettings& getTempSettings() { return lssPerm; }
254 
255  // setter methods
256  LogStream& setMessageType (std::string mt, const bool permanent = false);
257  LogStream& setSeverity (std::string ms, const bool permanent = false);
258  LogStream& setMessageType (log_type mt, const bool permanent = false) { if(permanent) { lssPerm.setMessageType(mt);} lssTemp.setMessageType(mt); return *this; }
259  LogStream& setSeverity (log_severity ms, const bool permanent = false) { if(permanent) { lssPerm.setSeverity (ms);} lssTemp.setSeverity (ms); return *this; }
260  LogStream& setEntityName (const std::string& en, const bool permanent = false) { if(permanent) { lssPerm.setEntityName (en);} lssTemp.setEntityName (en); return *this; }
261  LogStream& setSource (const std::string& s , const bool permanent = false) { if(permanent) { lssPerm.setSource (s) ;} lssTemp.setSource (s) ; return *this; }
262  LogStream& setLevel (manip_func1 f) { f(*this, true); return *this; }
263 
264  void setOutFilePath (std::string path) { outFilePath = path; }
265  void setLog2consoleFlag(bool b) { log2consoleFlag = b; }
266  void set2ReOpen ();
267  void setMaxBufferSize (unsigned int i) { maxBufferSize = i; }
268 
269  private:
270  template<typename T>
271  void put (const T t) { mBuf << t; } // Writes a value (template)
272  void put (const std::string &s) { mBuf << s; } // Writes a value
273  void do_write (bool b = false);
274  void start_write ();
275  void end_write ();
276  void write (); // Writes to the underlying logging object. This results in a new, timestamped line in the logfile.
277  void locked_write(std::string &s);
278  void openLogFile ();
279  void writeLogFile();
280 
281  LogStreamSettings lssTemp; // temporary settings
282  std::ostringstream mBuf; // The buffer where the log message is built up in.
283 
284  static bool doFlush;
285  static LogStreamSettings lssPerm; // perminant settings
286  static bool log2consoleFlag;
287  static boost::mutex objMutex;
288  static std::string outFilePath;
289  static std::ofstream outFile;
290  static std::deque<std::string> stringPool;
291  static unsigned int maxBufferSize; // the maximum number of log lines in stringPool, before a write is forced.
292  };
293 
294  //--------------------------------------------------------------------------------
295  // Internally-used helper constructs.
296  // The output operator used to write manipulators that take a single parameter.
297  // s - The log stream.
298  // m - The manipulator functor (internally used).
299  // return A reference to the modified log stream.
300  template<typename T>
301  inline LogStream& operator<< (LogStream& s, ManipResult<T> m) { return m(s); }
302 
303  //--------------------------------------------------------------------------------
304  // What makes these cases unique is that insertion operator is being passed the
305  // result of a function call, as opposed to a function pointer
306  // ss << "Testing, 1 2 3" << kisscpp::manip::endl;
307  // T - The manipulator's argument type.
308  template<typename T> class ManipResult
309  {
310  public:
311  typedef LogStream& (*func_type) (LogStream&, T); // The function type.
312 
313  ManipResult(func_type f, T t) : mFunc(f), mT(t) {} // f - The function.
314  // t - The manipulator's parameter.
315  // Stored until operator<< calls operator(), which will pass in the stream.
316 
317  LogStream& operator()(LogStream& s) { return mFunc(s, mT); } // Calls the stored function, passing into it its stream argument and the stored parameter.
318  private:
319  func_type mFunc; // The function.
320  T mT; // The parameter that will be passed into @a func.
321  };
322 
323  //--------------------------------------------------------------------------------
324  namespace manip
325  {
326  // Flushes the stream (write a line to the log).
327  inline LogStream& flush (LogStream& s) { return s.flush(); };
328  inline LogStream& endl (LogStream& s) { return s.endl (); };
329 
330  // Enables decimal, hexadicimal and octal output for numbers.
331  inline LogStream& dec (LogStream& s) { return s.dec (); };
332  inline LogStream& hex (LogStream& s) { return s.hex (); };
333  inline LogStream& oct (LogStream& s) { return s.oct (); };
334 
335  // Show the base when writing numbers.
336  inline LogStream& base (LogStream& s) { return s.base (); };
337 
338  // Sets the log type
339  inline LogStream& error (LogStream& s, const bool permanent) { return s.setMessageType(LT_ERROR , permanent); };
340  inline LogStream& info (LogStream& s, const bool permanent) { return s.setMessageType(LT_INFO , permanent); };
341  inline LogStream& debug (LogStream& s, const bool permanent) { return s.setMessageType(LT_DEBUG , permanent); };
342 
343  // Sets the log severity
344  inline LogStream& high (LogStream& s, const bool permanent) { return s.setSeverity (LS_HIGH , permanent); };
345  inline LogStream& normal (LogStream& s, const bool permanent) { return s.setSeverity (LS_NORMAL, permanent); };
346  inline LogStream& low (LogStream& s, const bool permanent) { return s.setSeverity (LS_LOW , permanent); };
347 
348  // Combined setting of log type and severity
349  inline LogStream& error_high (LogStream& s, const bool permanent) { return error(high (s, permanent), permanent); };
350  inline LogStream& error_normal(LogStream& s, const bool permanent) { return error(normal(s, permanent), permanent); };
351  inline LogStream& error_low (LogStream& s, const bool permanent) { return error(low (s, permanent), permanent); };
352  inline LogStream& debug_high (LogStream& s, const bool permanent) { return debug(high (s, permanent), permanent); };
353  inline LogStream& debug_normal(LogStream& s, const bool permanent) { return debug(normal(s, permanent), permanent); };
354  inline LogStream& debug_low (LogStream& s, const bool permanent) { return debug(low (s, permanent), permanent); };
355  inline LogStream& info_high (LogStream& s, const bool permanent) { return info (high (s, permanent), permanent); };
356  inline LogStream& info_normal (LogStream& s, const bool permanent) { return info (normal(s, permanent), permanent); };
357  inline LogStream& info_low (LogStream& s, const bool permanent) { return info (low (s, permanent), permanent); };
358 
359  namespace helpers
360  {
361  inline LogStream& ent (LogStream& s, std::string ent_name) { s.setEntityName(ent_name, false); return s; }
362  inline LogStream& source(LogStream& s, std::string source ) { s.setSource (source , false); return s; }
363  }
364 
365  // Sets the message's entity. A better name for this would've been "subject", perhaps. An example would be a transaction id.
366  inline ManipResult<std::string> ent (const std::string& ent_name) { return ManipResult<std::string>(manip::helpers::ent , ent_name); };
367 
368  // Sets the message's source. This would be, for example, the name of the calling object/function
370  };
371 
372 #pragma GCC visibility pop
373 
374 }
375 
376 #endif
LogStream & source(LogStream &s, std::string source)
Definition: logstream.hpp:362
const std::string & getEntityName() const
Definition: logstream.hpp:250
LogStream & high(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:344
LogStream & setLevel(manip_func1 f)
Definition: logstream.hpp:262
A purely informational log.
Definition: logstream.hpp:41
LogStreamSettings & getTempSettings()
Definition: logstream.hpp:253
LogStream & low(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:346
LogStreamSettings & getPermSettings()
Definition: logstream.hpp:252
LogStream & hex()
Definition: logstream.hpp:242
void setOutFilePath(std::string path)
Definition: logstream.hpp:264
log_severity getSeverity() const
Definition: logstream.hpp:249
High.
Definition: logstream.hpp:49
LogStream & base(LogStream &s)
Definition: logstream.hpp:336
log_severity
Used in conjunction with log_type as a log filter.
Definition: logstream.hpp:46
Definition: logstream.hpp:111
LogStream & error_high(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:349
LogStream & info(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:340
LogStream & setSeverity(std::string ms, const bool permanent=false)
Definition: logstream.cpp:44
LogStream & setSeverity(log_severity ms, const bool permanent=false)
Definition: logstream.hpp:259
LogStream & ent(LogStream &s, std::string ent_name)
Definition: logstream.hpp:361
log_type
Used in conjunction with log_serverity as a log filter.
Definition: logstream.hpp:39
LogStream(const std::string &src)
Definition: logstream.hpp:171
~LogStream()
Definition: logstream.hpp:204
LogStream & info_low(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:357
Normal.
Definition: logstream.hpp:48
LogStream & normal(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:345
A log for debugging purposes only.
Definition: logstream.hpp:40
const std::string & getSource() const
Definition: logstream.hpp:251
Low.
Definition: logstream.hpp:47
LogStream & operator<<(LogStream &s, ManipResult< T > m)
Definition: logstream.hpp:301
LogStream & hex(LogStream &s)
Definition: logstream.hpp:332
LogStream & dec()
Definition: logstream.hpp:241
#define DEFAULT_MAX_BUFF_SIZE
Definition: logstream.hpp:33
ManipResult< std::string > src(const std::string &source)
Definition: logstream.hpp:369
const std::string & getSource() const
Definition: logstream.hpp:130
LogStream & endl()
Definition: logstream.hpp:238
LogStream & error_normal(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:350
LogStream & debug_normal(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:353
LogStream & setMessageType(std::string mt, const bool permanent=false)
Definition: logstream.cpp:33
ManipResult(func_type f, T t)
Definition: logstream.hpp:313
ManipResult< std::string > ent(const std::string &ent_name)
Definition: logstream.hpp:366
Definition: logstream.hpp:145
LogStream(const std::string &src, const std::string &path, const bool log2console=false, const unsigned int i=DEFAULT_MAX_BUFF_SIZE)
Definition: logstream.hpp:181
void setLog2consoleFlag(bool b)
Definition: logstream.hpp:265
LogStream & operator=(const LogStream &o)
Definition: logstream.hpp:210
LogStream & info_normal(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:356
Definition: logstream.hpp:57
LogStream & debug(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:341
void setEntityName(const std::string &en)
Definition: logstream.hpp:134
LogStream & operator()(LogStream &s)
Definition: logstream.hpp:317
void setMessageType(log_type mt)
Definition: logstream.hpp:132
const std::string & getEntityName() const
Definition: logstream.hpp:129
LogStream & error(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:339
LogStream & setSource(const std::string &s, const bool permanent=false)
Definition: logstream.hpp:261
LogStream(const LogStream &o)
Definition: logstream.hpp:196
LogStream & flush(LogStream &s)
Definition: logstream.hpp:327
log_severity getSeverity() const
Definition: logstream.hpp:128
void setMaxBufferSize(unsigned int i)
Definition: logstream.hpp:267
log_type getMessageType() const
Definition: logstream.hpp:127
void setSource(const std::string &s)
Definition: logstream.hpp:135
LogStreamSettings & operator=(const LogStreamSettings &lss)
Definition: logstream.hpp:116
LogStream & base()
Definition: logstream.hpp:245
LogStream & debug_low(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:354
LogStream & dec(LogStream &s)
Definition: logstream.hpp:331
LogStreamSettings()
Definition: logstream.hpp:114
LogStream & setEntityName(const std::string &en, const bool permanent=false)
Definition: logstream.hpp:260
void setSeverity(log_severity ms)
Definition: logstream.hpp:133
log_type getMessageType() const
Definition: logstream.hpp:248
An error log.
Definition: logstream.hpp:42
LogStream & oct()
Definition: logstream.hpp:243
LogStream & setMessageType(log_type mt, const bool permanent=false)
Definition: logstream.hpp:258
LogStream & endl(LogStream &s)
Definition: logstream.hpp:328
LogStream & oct(LogStream &s)
Definition: logstream.hpp:333
LogStream(manip_func1 manip=info_normal)
Definition: logstream.hpp:154
LogStream & debug_high(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:352
LogStream & flush()
Definition: logstream.hpp:237
LogStream & info_high(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:355
LogStream & error_low(LogStream &s, const bool permanent=false)
Definition: logstream.hpp:351
LogStream(manip_func1 manip, const std::string &src)
Definition: logstream.hpp:162