RCFProto

- Main Page
- Classes
- Files

- File List

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