MIRA
LoggingCore.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_LOGGINGCORE_H_
48 #define _MIRA_LOGGINGCORE_H_
49 
50 #include <map>
51 
52 #ifndef Q_MOC_RUN
53 #include <boost/thread/mutex.hpp>
54 #include <boost/function.hpp>
55 #endif
56 
57 #include <platform/Types.h>
58 #include <thread/ThreadID.h>
59 #include <utils/Singleton.h>
60 #include <utils/Time.h>
61 #include <utils/Foreach.h>
63 
64 namespace mira {
65 
67 
73 {
74  CRITICAL = 0,
75  ERROR = 1,
76  WARNING = 2,
77  NOTICE = 3,
78  DEBUG = 4,
79  TRACE = 5,
80 };
81 
85 const std::string severityLevelStr[]= {
86  "CRITICAL",
87  "ERROR ",
88  "WARNING ",
89  "NOTICE ",
90  "DEBUG ",
91  "TRACE "
92 };
93 
99 MIRA_BASE_EXPORT SeverityLevel stringToSeverityLevel(const std::string& levelString);
100 
102 
107 struct LogRecord
108 {
112  std::string message;
113  std::string details;
114  int line;
115  std::string file;
116  std::string function;
118 };
119 
126 {
127  std::string nameSpace;
128  std::string className;
129  std::string functionName;
130 };
131 
136 template<typename Reflector>
137 void reflect(Reflector& r, LogRecord& record)
138 {
139  r.member("level", record.level, "Log level");
140  r.member("time", record.time, "Log time");
141  r.member("uptime", record.uptime, "Log uptime");
142  r.member("message", record.message, "Log message");
143  r.member("line", record.line, "Line in file where log call occurred");
144  r.member("file", record.file, "File where log call occurred");
145  r.member("function", record.function, "Function where log call occurred");
146  r.member("threadID", record.threadID, "ID of thread where log call occurred");
147 }
148 
150 
156 {
157 public:
158 
160  virtual ~LogFormatterBase() {}
161 
167  virtual std::string format(const LogRecord& record) = 0;
168 };
169 
171 typedef boost::shared_ptr<LogFormatterBase> LogFormatterPtr;
172 
174 
184 {
185 public:
186 
188  virtual ~LogFilterBase() {}
189 
195  virtual bool filter(const LogRecord& record) = 0;
196 };
197 
199 typedef boost::shared_ptr<LogFilterBase> LogFilterPtr;
200 
202 
209 {
210 public:
211 
213  virtual ~LogSink() {}
214 
219  void aboutToConsume(const LogRecord& record);
220 
226  virtual void consume(const LogRecord& record) = 0;
227 
232  void resetFilter()
233  {
234  mFilter.reset();
235  }
236 
242  template <typename T>
243  LogFilterPtr setFilter(const T& filter)
244  {
245  mFilter.reset(new T(filter));
246  return mFilter;
247  }
248 
254  {
255  mFormatter.reset();
256  }
257 
263  template <typename T>
264  LogFormatterPtr setFormatter(const T& formatter)
265  {
266  mFormatter.reset(new T(formatter));
267  return mFormatter;
268  }
269 
270 protected:
273 };
274 
276 typedef boost::shared_ptr<LogSink> LogSinkPtr;
277 
279 
286 class MIRA_BASE_EXPORT LogCore : public LazySingleton<LogCore>
287 {
288 public:
289 
291  typedef boost::function<void(SeverityLevel)> SeverityLevelChangedCallback;
292 
296  LogCore();
297 
303  LogRecordFunctionInfo parseFunction(const LogRecord& record);
304 
310  {
311  boost::mutex::scoped_lock lock(mCallbackMutex);
312  mSeverityLevel = level;
313  foreach(auto i, mSeverityChangedCallbacks)
314  i.second(level);
315  }
316 
322  {
323  return mSeverityLevel;
324  }
325 
332  {
333  boost::mutex::scoped_lock lock(mCallbackMutex);
334  mSeverityChangedCallbacks[mCallbackCounter] = callback;
335  return mCallbackCounter++;
336  }
337 
341  void unregisterCallback(uint32 id)
342  {
343  boost::mutex::scoped_lock lock(mCallbackMutex);
344  mSeverityChangedCallbacks.erase(id);
345  }
346 
352  {
353  return Time::now()-mStartTime;
354  }
355 
362  template <typename T>
363  LogSinkPtr registerSink(const T& sink)
364  {
365  boost::mutex::scoped_lock lock(mSinkMutex);
366  LogSinkPtr ptr(new T(sink));
367  mSinks.push_back(ptr);
368  return ptr;
369  }
370 
376  {
377  boost::mutex::scoped_lock lock(mSinkMutex);
378  auto i = mSinks.begin();
379  for (; i!= mSinks.end(); ++i)
380  if ((*i) == sink)
381  break;
382  if (i != mSinks.end())
383  mSinks.erase(i);
384  }
385 
392  void log(LogRecord& record)
393  {
394  boost::mutex::scoped_lock lock(mSinkMutex);
395  record.uptime = getUptime();
396  for(size_t i=0; i<mSinks.size(); ++i)
397  mSinks[i]->aboutToConsume(record);
398  }
399 
400 private:
401  boost::mutex mSinkMutex;
402  boost::mutex mCallbackMutex;
403  Time mStartTime;
404  SeverityLevel mSeverityLevel;
405  std::vector<LogSinkPtr> mSinks;
406  uint32 mCallbackCounter;
407  std::map<uint32, SeverityLevelChangedCallback> mSeverityChangedCallbacks;
408 };
409 
411 
417 #define MIRA_LOGGER (mira::LogCore::instance())
418 
427 class Logger : boost::noncopyable
428 {
429 public:
434  const Time& time,
435  const std::string& file, int line,
436  const std::string& function, ThreadID threadID)
437  {
438  mRecord.level = level;
439  mRecord.time = time;
440  mRecord.file = file;
441  mRecord.line = line;
442  mRecord.function = function;
443  mRecord.threadID = threadID;
444  }
445 
448  {
449  mStream.flush();
450  mRecord.message = mStream.str();
451  MIRA_LOGGER.log(mRecord);
452  }
457  std::ostringstream& stream()
458  {
459  return mStream;
460  }
461 
462 protected:
463 
465  std::ostringstream mStream;
466 };
467 
469 
480 #ifndef MIRA_SEVERITY_MAX_LEVEL
481 # ifdef NDEBUG
482 # define MIRA_SEVERITY_MAX_LEVEL mira::NOTICE
483 # else
484 # define MIRA_SEVERITY_MAX_LEVEL mira::TRACE
485 # endif
486 #endif
487 
529 #define MIRA_LOG(level) \
530 if (level > MIRA_SEVERITY_MAX_LEVEL) {} \
531 else if (constexpr auto fileInMIRAPath = mira::chopMIRAPath(__FILE__); level > MIRA_LOGGER.getSeverityLevel()) {} \
532  else mira::Logger(level, mira::Time::now(), fileInMIRAPath, __LINE__, MIRA_FUNCTION, mira::getCurrentThreadID()).stream()
533 
542 #define MIRA_LOG_ALWAYS(level) \
543 if constexpr (constexpr auto fileInMIRAPath = mira::chopMIRAPath(__FILE__); true) \
544  mira::Logger(level, mira::Time::now(), fileInMIRAPath, __LINE__, MIRA_FUNCTION, mira::getCurrentThreadID()).stream()
545 
550 #define MIRA_LOG_ATTR(level, time, file, line, function, threadID) \
551 if (level > MIRA_SEVERITY_MAX_LEVEL) {} \
552 else if (constexpr auto fileInMIRAPath = mira::chopMIRAPath(__FILE__); level > MIRA_LOGGER.getSeverityLevel()) {} \
553  else mira::Logger(level, time, file, line, function, threadID).stream()
554 
555 #define MIRA_TRACE MIRA_LOG(mira::TRACE) << "in : " << fileInMIRAPath << "(" << __LINE__ << ") in " << MIRA_FUNCTION << " "
556 
558 
559 }
560 
561 #endif
Macro for iterating over all elements in a container.
SeverityLevel level
Definition: LoggingCore.h:109
LogFilterPtr mFilter
Definition: LoggingCore.h:272
Typedefs for OS independent basic data types.
boost::function< void(SeverityLevel)> SeverityLevelChangedCallback
Signature of a callback function for log severity level changes.
Definition: LoggingCore.h:291
Single instance of the core logging class.
Definition: LoggingCore.h:286
virtual ~LogFormatterBase()
Destructor.
Definition: LoggingCore.h:160
Holds all the information about a log entry.
Definition: LoggingCore.h:107
Duration uptime
Definition: LoggingCore.h:111
virtual std::string format(const LogRecord &record)=0
Creates a formatted string out of a log entry.
void unregisterSink(LogSinkPtr sink)
Unregisters a sink.
Definition: LoggingCore.h:375
LogSinkPtr registerSink(const T &sink)
Register a new sink.
Definition: LoggingCore.h:363
std::string function
Definition: LoggingCore.h:116
~Logger()
Destructor.
Definition: LoggingCore.h:447
PropertyHint file(const std::string &filters=std::string(), bool save=false)
Tells the property editor that the path is for a file, and that it should show a "File Open"/"File Sa...
Definition: Path.h:247
Duration getUptime() const
Get the up-time of the core.
Definition: LoggingCore.h:351
Abstract base class for log filters.
Definition: LoggingCore.h:183
boost::shared_ptr< LogSink > LogSinkPtr
A shared pointer for a log sink.
Definition: LoggingCore.h:276
Holds information about a log entry function.
Definition: LoggingCore.h:125
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
Compile-time path handling.
void resetFilter()
Resets the log filter.
Definition: LoggingCore.h:232
std::string nameSpace
Definition: LoggingCore.h:127
Time and Duration wrapper class.
Helper class that is created to make one logging process atomic and thread safe.
Definition: LoggingCore.h:427
uint32 ThreadID
Platform independent thread ID.
Definition: ThreadID.h:68
Definition: LoggingCore.h:79
Provided for convenience.
Definition: Singleton.h:564
SeverityLevel
Severity levels to graduate between different log outputs.
Definition: LoggingCore.h:72
Logger(SeverityLevel level, const Time &time, const std::string &file, int line, const std::string &function, ThreadID threadID)
The constructor taking the details of a log entry.
Definition: LoggingCore.h:433
LogFormatterPtr setFormatter(const T &formatter)
Set the formatter.
Definition: LoggingCore.h:264
std::ostringstream mStream
Definition: LoggingCore.h:465
void unregisterCallback(uint32 id)
Unregister a callback function.
Definition: LoggingCore.h:341
Wrapper class for boost::posix_time::ptime for adding more functionality to it.
Definition: Time.h:416
OS independent thread id.
int line
Definition: LoggingCore.h:114
std::string file
Definition: LoggingCore.h:115
LogFilterPtr setFilter(const T &filter)
Set the filter.
Definition: LoggingCore.h:243
boost::shared_ptr< LogFormatterBase > LogFormatterPtr
A shared pointer for a log formatter.
Definition: LoggingCore.h:171
A singleton class that can be freely configured using policies that control the creation, instantiation, lifetime and thread-safety.
Use this class to represent time durations.
Definition: Time.h:104
uint32 registerCallback(SeverityLevelChangedCallback callback)
Register a callback function.
Definition: LoggingCore.h:331
void resetFormatter()
Resets the formatter.
Definition: LoggingCore.h:253
std::string message
Definition: LoggingCore.h:112
void reflect(Reflector &r, LogRecord &record)
Non-intrusive reflector for LogRecord.
Definition: LoggingCore.h:137
void setSeverityLevel(SeverityLevel level)
Sets the application wide severity level.
Definition: LoggingCore.h:309
void log(LogRecord &record)
Writes a log record and distribute it between all the registered sinks.
Definition: LoggingCore.h:392
std::string className
Definition: LoggingCore.h:128
virtual ~LogFilterBase()
Destructor.
Definition: LoggingCore.h:188
boost::shared_ptr< LogFilterBase > LogFilterPtr
A shared pointer for a log filter.
Definition: LoggingCore.h:199
Abstract base class for sink formatters.
Definition: LoggingCore.h:155
ThreadID threadID
Definition: LoggingCore.h:117
const std::string severityLevelStr[]
String conversion for the enum severity types.
Definition: LoggingCore.h:85
Time time
Definition: LoggingCore.h:110
Abstract base class for all log sinks.
Definition: LoggingCore.h:208
Definition: LoggingCore.h:76
static Time now() static Time eternity()
Returns the current utc based time.
Definition: Time.h:479
MIRA_BASE_EXPORT SeverityLevel stringToSeverityLevel(const std::string &levelString)
Converts the specified string into a numeric severity level.
Definition: LoggingCore.h:74
virtual bool filter(const LogRecord &record)=0
Filters a log entry.
Definition: LoggingCore.h:78
#define MIRA_BASE_EXPORT
This is required because on windows there is a macro defined called ERROR.
Definition: Platform.h:153
std::string functionName
Definition: LoggingCore.h:129
Definition: LoggingCore.h:75
SeverityLevel getSeverityLevel() const
Get the application wide severity level.
Definition: LoggingCore.h:321
LogRecord mRecord
Definition: LoggingCore.h:464
virtual ~LogSink()
Destructor.
Definition: LoggingCore.h:213
std::string details
Definition: LoggingCore.h:113
LogFormatterPtr mFormatter
Definition: LoggingCore.h:271
Definition: LoggingCore.h:77
#define MIRA_LOGGER
Macro for easier access to the logging core instance.
Definition: LoggingCore.h:417
std::ostringstream & stream()
Get the underlying stream.
Definition: LoggingCore.h:457