versatile-mcmc  0.1.7
logger.hpp
Go to the documentation of this file.
1 
13 #ifndef VMCMC_LOGGER_H_
14 #define VMCMC_LOGGER_H_
15 
16 
17 // UTILITY MACROS
18 
19 #define STRINGIFY(x) #x
20 #define TOSTRING(x) STRINGIFY(x)
21 #define __FILE_LINE__ __FILE__ " (" TOSTRING(__LINE__) ")"
22 #define __FILENAME_LINE__ (strrchr(__FILE__, '/') ? strrchr(__FILE_LINE__, '/') + 1 : __FILE_LINE__)
23 
24 #if defined(_MSC_VER)
25 #if _MSC_VER >= 1300
26  #define __FUNC__ __FUNCSIG__
27 #endif
28 #else
29 #if defined(__GNUC__)
30  #define __FUNC__ __PRETTY_FUNCTION__
31 #endif
32 #endif
33 #if !defined(__FUNC__)
34 #define __FUNC__ ""
35 #endif
36 
37 #define va_num_args(...) va_num_args_impl(__VA_ARGS__, 5,4,3,2,1)
38 #define va_num_args_impl(_1,_2,_3,_4,_5,N,...) N
39 
40 #define macro_dispatcher(func, ...) macro_dispatcher_(func, va_num_args(__VA_ARGS__))
41 #define macro_dispatcher_(func, nargs) macro_dispatcher__(func, nargs)
42 #define macro_dispatcher__(func, nargs) func ## nargs
43 
44 // INCLUDES
45 
46 #include <string>
47 #include <iostream>
48 #include <sstream>
49 #include <mutex>
50 
51 namespace vmcmc {
52 
81 class Logger
82 {
83 public:
84  enum class ELevel {
85  Trace, Debug, Info, Warn, Error, Fatal, Undefined
86  };
87 
88 public:
93  struct Location {
94  Location(const char* const fileName = "", const char* const functionName = "", int lineNumber = -1);
95  int fLineNumber;
96  std::string fFileName;
97  std::string fFunctionName;
98  };
99 
100 public:
105  Logger(const std::string& name = "");
106 
107  virtual ~Logger();
108 
109  std::mutex& GetMutex() { static std::mutex sMutex; return sMutex; }
110 
116  bool IsLevelEnabled(ELevel level) const { return fMinLevel <= level; }
117 
122  ELevel GetLevel() const { return fMinLevel; }
123 
128  void SetLevel(ELevel level) { fMinLevel = level; }
129 
134  void SetColoured(bool coloured) { fColouredOutput = coloured; }
135 
143  void StartMessage(ELevel level, const Location& loc = Location());
144 
150  std::ostream& Log() { return *fActiveStream; }
151 
156  void EndMessage();
157 
158 private:
159  std::string fName;
160  std::ostream* fActiveStream;
161  ELevel fMinLevel;
162  bool fColouredOutput;
163 };
164 
165 } /* namespace vmcmc */
166 
167 // PRIVATE MACROS
168 
169 #define __LOG_LOCATION vmcmc::Logger::Location(__FILE__, __FUNC__, __LINE__)
170 
171 #define __LOG_DEFINE_2(I,K) static vmcmc::Logger I(K);
172 #define __LOG_DEFINE_1(K) static vmcmc::Logger sLocalLoggerInstance(K);
173 
174 #define __LOG_3(I,L,M) \
175 { \
176  if (I.IsLevelEnabled(vmcmc::Logger::ELevel::L)) { \
177  std::lock_guard<std::mutex> _logLock(I.GetMutex()); \
178  I.StartMessage(vmcmc::Logger::ELevel::L, __LOG_LOCATION); \
179  I.Log() << M; \
180  I.EndMessage(); \
181  } \
182 }
183 
184 #define __LOG_ONCE_3(I,L,M) \
185 { \
186  if (I.IsLevelEnabled(vmcmc::Logger::ELevel::L)) { \
187  static bool _sLogMarker = false; \
188  std::lock_guard<std::mutex> _logLock(I.GetMutex()); \
189  if (!_sLogMarker) { \
190  _sLogMarker = true; \
191  I.StartMessage(vmcmc::Logger::ELevel::L, __LOG_LOCATION); \
192  I.Log() << M; \
193  I.EndMessage(); \
194  } \
195  } \
196 }
197 
198 #define __LOG_ASSERT_3(I,C,M) \
199 { \
200  if (I.IsLevelEnabled(vmcmc::Logger::ELevel::Debug) && !(C)) { \
201  std::lock_guard<std::mutex> _logLock(I.GetMutex()); \
202  I.StartMessage(vmcmc::Logger::ELevel::Fatal, __LOG_LOCATION); \
203  I.Log() << "Assertion '(" << TOSTRING(C) << ")' failed. " << M; \
204  I.EndMessage(); \
205  abort(); \
206  } \
207 }
208 
209 #define __LOG_2(L,M) __LOG_3(sLocalLoggerInstance,L,M)
210 #define __LOG_1(M) __LOG_3(sLocalLoggerInstance,Debug,M)
211 
212 #define __LOG_ONCE_2(L,M) __LOG_ONCE_3(sLocalLoggerInstance,L,M)
213 #define __LOG_ONCE_1(M) __LOG_ONCE_3(sLocalLoggerInstance,Debug,M)
214 
215 #define __LOG_ASSERT_1(C) __LOG_ASSERT_3(sLocalLoggerInstance,C,"")
216 #define __LOG_ASSERT_2(C,M) __LOG_ASSERT_3(sLocalLoggerInstance,C,M)
217 
218 
219 // PUBLIC MACROS
220 
221 #define LOG_DEFINE(...) macro_dispatcher(__LOG_DEFINE_, __VA_ARGS__)(__VA_ARGS__)
222 
223 #define LOG(...) macro_dispatcher(__LOG_, __VA_ARGS__)(__VA_ARGS__)
224 
225 #define LOG_ONCE(...) macro_dispatcher(__LOG_ONCE_, __VA_ARGS__)(__VA_ARGS__)
226 #define LOG_ASSERT(...) macro_dispatcher(__LOG_ASSERT_, __VA_ARGS__)(__VA_ARGS__)
227 
228 
229 #endif /* VMCMC_LOGGER_H_ */
void SetLevel(ELevel level)
Set a loggers minimum logging level.
Definition: logger.hpp:128
A simple MACRO-focussed logging facility.
Definition: logger.hpp:81
Definition: algorithm.cpp:28
std::ostream & Log()
Get an output stream for log messages to append.
Definition: logger.hpp:150
A simple struct used by the Logger macros to pass information about the filename and line number...
Definition: logger.hpp:93
bool IsLevelEnabled(ELevel level) const
Check whether a certain log-level is enabled.
Definition: logger.hpp:116
void EndMessage()
End and flush the last message.
Definition: logger.cpp:131
void StartMessage(ELevel level, const Location &loc=Location())
Start a message with the specified level.
Definition: logger.cpp:109
void SetColoured(bool coloured)
Set whether the output should be coloured or not.
Definition: logger.hpp:134
ELevel GetLevel() const
Get a loggers minimum logging level.
Definition: logger.hpp:122
Logger(const std::string &name="")
Standard constructor assigning a name to the logger instance.
Definition: logger.cpp:95