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