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