RCFProto
 All Classes Functions Typedefs
Log.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef INCLUDE_UTIL_LOG_HPP
20 #define INCLUDE_UTIL_LOG_HPP
21 
22 #include <fstream>
23 #include <map>
24 #include <string>
25 #include <vector>
26 
27 #include <boost/config.hpp>
28 #include <boost/current_function.hpp>
29 #include <boost/enable_shared_from_this.hpp>
30 #include <boost/function.hpp>
31 #include <boost/scoped_ptr.hpp>
32 #include <boost/shared_ptr.hpp>
33 
34 #include <RCF/Export.hpp>
35 #include <RCF/ThreadLibrary.hpp>
36 
37 #include <RCF/util/Tchar.hpp>
38 #include <RCF/util/VariableArgMacro.hpp>
39 
40 #ifdef BOOST_WINDOWS
41 #include <Windows.h>
42 #endif
43 
44 namespace RCF {
45 
46  class ByteBuffer;
47 
48  class LogBuffers
49  {
50  public:
51  RCF::MemOstream mTlsUserBuffer;
52  RCF::MemOstream mTlsLoggerBuffer;
53  RCF::MemOstream mTlsVarArgBuffer1;
54  RCF::MemOstream mTlsVarArgBuffer2;
55  };
56 
57  //******************************************************************************
58  // LogManager
59 
60  class LogEntry;
61  class Logger;
62 
63  typedef boost::shared_ptr<Logger> LoggerPtr;
64 
65  class RCF_EXPORT LogManager
66  {
67  private:
68  LogManager();
69  ~LogManager();
70 
71  public:
72  static void init();
73  static void deinit();
74  static LogManager & instance();
75 
76  void deactivateAllLoggers();
77  void deactivateAllLoggers(int name);
78 
79  bool isEnabled(int name, int level);
80 
81  typedef std::map< int, std::vector< LoggerPtr > > Loggers;
82  ReadWriteMutex mLoggersMutex;
83  Loggers mLoggers;
84 
85  void writeToLoggers(const LogEntry & logEntry);
86  void activateLogger(LoggerPtr loggerPtr);
87  void deactivateLogger(LoggerPtr loggerPtr);
88  bool isLoggerActive(LoggerPtr loggerPtr);
89 
90  const std::string DefaultLogFormat;
91 
92  Mutex DefaultLoggerPtrMutex;
93  LoggerPtr DefaultLoggerPtr;
94  };
95 
96  //******************************************************************************
97  // LogTarget
98 
99  class LogTarget;
100  typedef boost::shared_ptr<LogTarget> LogTargetPtr;
101 
104  class RCF_EXPORT LogTarget
105  {
106  public:
107  virtual ~LogTarget() {}
108  virtual LogTarget * clone() const = 0;
109  virtual void write(const RCF::ByteBuffer & output) = 0;
110  };
111 
113  class RCF_EXPORT LogToStdout : public LogTarget
114  {
115  public:
116  LogToStdout(bool flushAfterEachWrite = true);
117  LogTarget * clone() const;
118  void write(const RCF::ByteBuffer & output);
119 
120  static RCF::Mutex sIoMutex;
121 
122  private:
123  bool mFlush;
124  };
125 
126 #ifdef BOOST_WINDOWS
127 
129  class RCF_EXPORT LogToDebugWindow : public LogTarget
130  {
131  public:
132  LogTarget * clone() const;
133  void write(const RCF::ByteBuffer & output);
134  };
135 
137  class RCF_EXPORT LogToEventLog : public LogTarget
138  {
139  public:
140  LogToEventLog(const std::string & appName, int eventLogLevel);
141  ~LogToEventLog();
142 
143  LogTarget * clone() const;
144  void write(const RCF::ByteBuffer & output);
145 
146  private:
147  std::string mAppName;
148  int mEventLogLevel;
149  HANDLE mhEventLog;
150  };
151 
152 #endif
153 
155  class RCF_EXPORT LogToFile : public LogTarget
156  {
157  public:
158  LogToFile(const std::string & filePath, bool flushAfterEachWrite = false);
159  LogToFile(const LogToFile & rhs);
160  LogTarget * clone() const;
161  void write(const RCF::ByteBuffer & output);
162 
163  private:
164 
165  RCF::Mutex mMutex;
166 
167  std::string mFilePath;
168  bool mOpened;
169  std::ofstream mFout;
170  bool mFlush;
171  };
172 
173  typedef boost::function1<void, const RCF::ByteBuffer &> LogFunctor;
174 
175  class RCF_EXPORT LogToFunc : public LogTarget
176  {
177  public:
178  LogToFunc(LogFunctor logFunctor);
179  LogTarget * clone() const;
180  void write(const RCF::ByteBuffer & output);
181 
182  private:
183  LogFunctor mLogFunctor;
184  };
185 
186  //******************************************************************************
187  // LogEntry
188 
189  class RCF_EXPORT LogEntry
190  {
191  public:
192 
193  LogEntry(int name, int level);
194  LogEntry(int name, int level, const char * szFile, int line, const char * szFunc);
195  ~LogEntry();
196 
197  // Pass everything through to mOstream.
198  template<typename T>
199  const LogEntry& operator<<(const T& t) const
200  {
201  const_cast<RCF::MemOstream&>(*mpOstream) << t;
202  return *this;
203  }
204 
205 #ifndef BOOST_NO_STD_WSTRING
206  const LogEntry& operator<<(const std::wstring& t) const
207  {
208  const_cast<RCF::MemOstream&>(*mpOstream) << RCF::wstringToString(t);
209  return *this;
210  }
211 #endif
212 
213  // Special streaming for std::endl etc.
214  typedef std::ostream& (*Pfn)(std::ostream&);
215  const LogEntry& operator<<(Pfn pfn) const
216  {
217  const_cast<RCF::MemOstream&>(*mpOstream) << pfn;
218  return *this;
219  }
220 
221  RCF::MemOstream & getOstream()
222  {
223  return *mpOstream;
224  }
225 
226  private:
227 
228  friend class LogManager;
229  friend class Logger;
230 
231  int mName;
232  int mLevel;
233  const char * mFile;
234  int mLine;
235  const char * mFunc;
236 
237  RCF::ThreadId mThreadId;
238  time_t mTime;
239  boost::uint32_t mTimeMs;
240 
241  RCF::MemOstream * mpOstream;
242  };
243 
244  //******************************************************************************
245  // Logger
246 
247  typedef boost::function2<void, const LogEntry &, RCF::ByteBuffer&> LogFormatFunctor;
248 
249  class RCF_EXPORT Logger : public boost::enable_shared_from_this<Logger>
250  {
251  public:
252  Logger(int name, int level, const LogTarget& logTarget, const std::string & logFormat = "");
253  Logger(int name, int level, const LogTarget& logTarget, LogFormatFunctor logFormatFunctor);
254 
255  Logger(int name, int level, LogTargetPtr logTargetPtr, const std::string & logFormat = "");
256  Logger(int name, int level, LogTargetPtr logTargetPtr, LogFormatFunctor logFormatFunctor);
257 
258  void setName(int name);
259  void setLevel(int level);
260  void setTarget(const LogTarget & logTarget);
261  void setFormat(const std::string & logFormat);
262 
263  int getName() const;
264  int getLevel() const;
265  const LogTarget& getTarget() const;
266  std::string getFormat() const;
267 
268  void write(const LogEntry & logEntry);
269 
270  void activate();
271  void deactivate();
272  bool isActive();
273 
274  private:
275 
276  int mName;
277  int mLevel;
278  LogTargetPtr mTargetPtr;
279  std::string mFormat;
280  LogFormatFunctor mFormatFunctor;
281  };
282 
283  typedef boost::shared_ptr<Logger> LoggerPtr;
284 
285  template<typename T>
286  class LogNameValue
287  {
288  public:
289  LogNameValue(const char * name, const T & value) :
290  mName(name),
291  mValue(value)
292  {
293  }
294 
295  const char * mName;
296  const T& mValue;
297 
298  friend std::ostream& operator<<(std::ostream & os, const LogNameValue& lnv)
299  {
300  os << "(" << lnv.mName << " = " << lnv.mValue << ")";
301  return os;
302  }
303  };
304 
305  template<typename T>
306  LogNameValue<T> makeNameValue(const char * name, const T & value)
307  {
308  return LogNameValue<T>(name, value);
309  }
310 
311  #define NAMEVALUE(x) RCF::makeNameValue(#x, x)
312 
313  class LogVarsFunctor : public util::VariableArgMacroFunctor
314  {
315  public:
316 
317  LogVarsFunctor() : mLogEntry(0, 0, NULL, 0, NULL)
318  {
319  }
320 
321  LogVarsFunctor(int name, int level, const char * file, int line, const char * szFunc) :
322  mLogEntry(name, level, file, line, szFunc)
323  {
324  }
325 
326  ~LogVarsFunctor()
327  {
328  if (mArgs->tellp() > 0)
329  {
330  mLogEntry << " [Args: ";
331  mLogEntry.getOstream().write(mArgs->str(), mArgs->tellp());
332  mLogEntry << "]";
333  }
334  }
335 
336  template<typename T>
337  const LogVarsFunctor & operator<<(const T & t) const
338  {
339  const_cast<LogEntry &>(mLogEntry) << t;
340  return *this;
341  }
342 
343  typedef std::ostream& (*Pfn)(std::ostream&);
344  const LogVarsFunctor & operator<<(Pfn pfn) const
345  {
346  const_cast<LogEntry &>(mLogEntry) << pfn;
347  return *this;
348  }
349 
350  private:
351  LogEntry mLogEntry;
352  };
353 
354 #if defined(_MSC_VER)
355 #pragma warning(push)
356 #pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list
357 #endif
358 
359  DECLARE_VARIABLE_ARG_MACRO( UTIL_LOG, LogVarsFunctor );
360 
361 #if defined(_MSC_VER)
362 #pragma warning(pop)
363 #endif
364 
365 #if defined(__GNUC__) && (__GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4))
366 #define UTIL_LOG_GCC_33_HACK (const RCF::VariableArgMacro<RCF::LogVarsFunctor> &)
367 #else
368 #define UTIL_LOG_GCC_33_HACK
369 #endif
370 
371  #define UTIL_LOG(name, level) \
372  if (RCF::LogManager::instance().isEnabled(name, level)) \
373  UTIL_LOG_GCC_33_HACK RCF::VariableArgMacro<RCF::LogVarsFunctor>( \
374  name, level, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) \
375  .cast( (RCF::VariableArgMacro<RCF::LogVarsFunctor> *) NULL ) \
376  .UTIL_LOG_A
377 
378  #define UTIL_LOG_A(x) UTIL_LOG_OP(x, B)
379  #define UTIL_LOG_B(x) UTIL_LOG_OP(x, A)
380  #define UTIL_LOG_OP(x, next) UTIL_LOG_A.notify_((x), #x).UTIL_LOG_ ## next
381 
382 
383 #ifdef BOOST_WINDOWS
384  typedef LogToDebugWindow DefaultLogTarget;
385 #else
386  typedef LogToStdout DefaultLogTarget;
387 #endif
388 
393  RCF_EXPORT void enableLogging(
394  const LogTarget & logTarget = DefaultLogTarget(),
395  int logLevel = 2,
396  const std::string & logFormat = "");
397 
399  RCF_EXPORT void disableLogging();
400 
401 } // namespace RCF
402 
403 #endif // ! INCLUDE_UTIL_LOG_HPP