Scarab  v3.4.3
Project 8 C++ Utility Library
logger.cc
Go to the documentation of this file.
1 /*
2  * logger.cxx
3  * based on KLogger.cxx from KATRIN's Kasper
4  *
5  * Created on: 18.11.2011
6  * Author: Marco Haag <marco.haag@kit.edu>
7  */
8 
9 #define SCARAB_API_EXPORTS
10 
11 
12 #include <algorithm>
13 #include <cstring> // for strrchr
14 #include <iomanip>
15 #include <iterator>
16 #include <mutex>
17 #include <set>
18 #include <time.h>
19 
20 #ifndef NDEBUG
21 #include <thread>
22 #endif
23 
24 #include "logger.hh"
25 
26 using namespace std;
27 
28 namespace scarab
29 {
30  const string& EndColor() {static string* color = new string(COLOR_PREFIX COLOR_NORMAL COLOR_SUFFIX); return *color;}
31  const string& FatalColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_RED COLOR_SUFFIX); return *color;}
32  const string& ErrorColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_RED COLOR_SUFFIX); return *color;}
33  const string& WarnColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_YELLOW COLOR_SUFFIX); return *color;}
34  const string& InfoColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_GREEN COLOR_SUFFIX); return *color;}
35  const string& ProgColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_BLUE COLOR_SUFFIX); return *color;}
36  const string& DebugColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_CYAN COLOR_SUFFIX); return *color;}
37  const string& TraceColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_WHITE COLOR_SUFFIX); return *color;}
38  const string& OtherColor() {static string* color = new string(COLOR_PREFIX COLOR_BRIGHT COLOR_SEPARATOR COLOR_FOREGROUND_WHITE COLOR_SUFFIX); return *color;}
39 
41  {
42  static std::mutex sMutex;
43 
44  typedef std::set< logger* > LoggerSet;
45  static std::shared_ptr<LoggerSet> AllLoggers()
46  {
47  // construct-on-first-use strategy to avoid static initialization fiasco
48  static std::shared_ptr<LoggerSet> sAllLoggers = std::make_shared< LoggerSet >();
49  return sAllLoggers;
50  }
51 
52  static char sDateTimeFormat[16];
53  static time_t sRawTime;
54  static tm* sProcessedTime;
55  static char sTimeBuff[512];
56  static size_t getTimeAbsoluteStr()
57  {
58  time(&logger::Private::sRawTime);
59 
60  sProcessedTime = localtime(&logger::Private::sRawTime);
61  return strftime(logger::Private::sTimeBuff, 512,
62  logger::Private::sDateTimeFormat,
63  logger::Private::sProcessedTime);
64  }
65 
66 
67  const char* fLogger;
68 
69  static bool fColored;
70 
71  static std::ostream* fOut;
72  static std::ostream* fErr;
73 
76 
78  {
79  // construct-on-first-use strategy to avoid static initialization fiasco
80  static ELevel sGlobalThreshold = logger::Private::filterMinimumLevel(ELevel::eDebug);
81  return sGlobalThreshold;
82  }
83 
84  static const char* level2Str(ELevel level)
85  {
86  switch(level)
87  {
88  case ELevel::eTrace : return "TRACE"; break;
89  case ELevel::eDebug : return "DEBUG"; break;
90  case ELevel::eInfo : return "INFO"; break;
91  case ELevel::eProg : return "PROG"; break;
92  case ELevel::eWarn : return "WARN"; break;
93  case ELevel::eError : return "ERROR"; break;
94  case ELevel::eFatal : return "FATAL"; break;
95  default : return "XXX";
96  }
97  }
98 
99  static string level2Color(ELevel level)
100  {
101  switch(level)
102  {
103  case ELevel::eTrace : return TraceColor(); break;
104  case ELevel::eDebug : return DebugColor(); break;
105  case ELevel::eInfo : return InfoColor(); break;
106  case ELevel::eProg : return ProgColor(); break;
107  case ELevel::eWarn : return WarnColor(); break;
108  case ELevel::eError : return ErrorColor(); break;
109  case ELevel::eFatal : return FatalColor(); break;
110  default : return OtherColor();
111  }
112  }
113 
115  {
116 #if defined(NDEBUG) && defined(STANDARD)
117  return level >= ELevel::eInfo ? level : ELevel::eInfo;
118 #elif defined(NDEBUG)
119  return level >= ELevel::eProg ? level : ELevel::eProg;
120 #else
121  return level;
122 #endif
123  }
124 
125 
126  void logCout(ELevel level, const string& message, const Location& loc)
127  {
128  logger::Private::sMutex.lock();
129  logger::Private::getTimeAbsoluteStr();
130  if (fColored)
131  {
132  //cout << color << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << skKTEndColor << endl;
133  (*fOut) << Private::level2Color(level) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
134 #ifndef NDEBUG
135  (*fOut) << "(tid " << std::this_thread::get_id() << ") ";
136 #endif
137  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fOut));
138  (*fOut) << "(" << loc.fLineNumber << "): ";
139  (*fOut) << message << EndColor() << endl;
140  }
141  else
142  {
143  //cout << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << endl;
144  (*fOut) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
145 #ifndef NDEBUG
146  (*fOut) << "(tid " << std::this_thread::get_id() << ") ";
147 #endif
148  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fOut));
149  (*fOut) << "(" << loc.fLineNumber << "): ";
150  (*fOut) << message << endl;
151  }
152  logger::Private::sMutex.unlock();
153  }
154 
155  void logCerr(ELevel level, const string& message, const Location& loc)
156  {
157  logger::Private::sMutex.lock();
158  logger::Private::getTimeAbsoluteStr();
159  if (fColored)
160  {
161  //cout << color << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << skKTEndColor << endl;
162  (*fErr) << Private::level2Color(level) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
163 #ifndef NDEBUG
164  (*fErr) << "(tid " << std::this_thread::get_id() << ") ";
165 #endif
166  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fErr));
167  (*fErr) << "(" << loc.fLineNumber << "): ";
168  (*fErr) << message << EndColor() << endl;
169  }
170  else
171  {
172  //cout << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << endl;
173  (*fErr) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
174 #ifndef NDEBUG
175  (*fErr) << "(tid " << std::this_thread::get_id() << ") ";
176 #endif
177  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fErr));
178  (*fErr) << "(" << loc.fLineNumber << "): ";
179  (*fErr) << message << endl;
180  }
181  logger::Private::sMutex.unlock();
182  }
183  };
184 
185  mutex logger::Private::sMutex;
186 
187  char logger::Private::sDateTimeFormat[16];
188  time_t logger::Private::sRawTime;
189  tm* logger::Private::sProcessedTime;
190  char logger::Private::sTimeBuff[512];
191 
192  bool logger::Private::fColored = true;
193 
194  std::ostream* logger::Private::fOut = &cout;
195  std::ostream* logger::Private::fErr = &cerr;
196 
197 
198  logger::logger(const char* name) : fPrivate(new Private())
199  {
200  if (name == 0)
201  {
202  fPrivate->fLogger = "root";
203  }
204  else
205  {
206  const char* logName = strrchr(name, '/') ? strrchr(name, '/') + 1 : name;
207  fPrivate->fLogger = logName;
208  }
209 #ifndef _WIN32
210  fPrivate->fColored = true;
211 #else
212  fPrivate->fColored = false;
213 #endif
214  sprintf(logger::Private::sDateTimeFormat, "%%Y-%%m-%%d %%T");
215  UseGlobalLevel();
216  logger::Private::AllLoggers()->insert(this);
217  }
218 
219  logger::logger(const std::string& name) : fPrivate(new Private())
220  {
221  fPrivate->fLogger = name.c_str();
222 #ifndef _WIN32
223  fPrivate->fColored = true;
224 #else
225  fPrivate->fColored = false;
226 #endif
227  sprintf(logger::Private::sDateTimeFormat, "%%Y-%%m-%%d %%T");
228  UseGlobalLevel();
229  logger::Private::AllLoggers()->insert(this);
230  }
231 
233  {
234  logger::Private::AllLoggers()->erase(this);
235  }
236 
237  bool logger::IsLevelEnabled(ELevel level) const
238  {
239  return level >= fPrivate->fThreshold;
240  }
241 
243  {
244  return fPrivate->fThreshold;
245  }
246 
247  void logger::SetLevel(ELevel level) const
248  {
249  fPrivate->fThreshold = logger::Private::filterMinimumLevel(level);
250  fPrivate->fThresholdIsGlobal = false;
251  }
252 
254  {
256  fPrivate->fThresholdIsGlobal = true;
257  }
258 
259  // static function
261  {
263  }
264 
265  // static function
267  {
269  for( logger::Private::LoggerSet::iterator logIt = logger::Private::AllLoggers()->begin(); logIt != logger::Private::AllLoggers()->end(); ++logIt)
270  {
271  if( (*logIt)->fPrivate->fThresholdIsGlobal )
272  {
273  (*logIt)->fPrivate->fThreshold = logger::Private::GlobalThreshold();
274  }
275  }
276  return;
277  }
278 
279  void logger::SetColored(bool flag)
280  {
281 #ifndef _WIN32
282  logger::Private::fColored = flag;
283 #else
284  std::cerr << "Colored logging is not enabled in Windows" << std::endl;
285 #endif
286  return;
287  }
288 
289  void logger::SetOutStream(std::ostream* stream)
290  {
291  logger::Private::fOut = stream;
292  return;
293  }
294 
295  void logger::SetErrStream(std::ostream* stream)
296  {
297  logger::Private::fErr = stream;
298  return;
299  }
300 
301  void logger::Log(ELevel level, const string& message, const Location& loc)
302  {
303  if (level >= ELevel::eWarn)
304  {
305  fPrivate->logCerr(level, message, loc);
306  }
307  else
308  {
309  fPrivate->logCout(level, message, loc);
310  }
311  }
312 }
std::string fFileName
Definition: logger.hh:141
#define COLOR_BRIGHT
Definition: logger.hh:45
ELevel GetLevel() const
Definition: logger.cc:242
const string & TraceColor()
Definition: logger.cc:37
const char * fLogger
Definition: logger.cc:67
const string & OtherColor()
Definition: logger.cc:38
const string & EndColor()
Definition: logger.cc:30
virtual ~logger()
Definition: logger.cc:232
void logCerr(ELevel level, const string &message, const Location &loc)
Definition: logger.cc:155
static time_t sRawTime
Definition: logger.cc:53
const string & FatalColor()
Definition: logger.cc:31
static bool fColored
Definition: logger.cc:69
static size_t getTimeAbsoluteStr()
Definition: logger.cc:56
#define COLOR_NORMAL
Definition: logger.hh:44
#define COLOR_SEPARATOR
Definition: logger.hh:54
static std::ostream * fErr
Definition: logger.cc:72
static ELevel & GlobalThreshold()
Definition: logger.cc:77
STL namespace.
void Log(ELevel level, const std::string &message, const Location &loc=Location())
Definition: logger.cc:301
#define COLOR_FOREGROUND_WHITE
Definition: logger.hh:51
static void SetColored(bool flag)
Definition: logger.cc:279
void UseGlobalLevel() const
Definition: logger.cc:253
Contains the logger class and macros, based on Kasper&#39;s KLogger class.
static const char * level2Str(ELevel level)
Definition: logger.cc:84
static string level2Color(ELevel level)
Definition: logger.cc:99
const string & ProgColor()
Definition: logger.cc:35
static void SetErrStream(std::ostream *stream)
Definition: logger.cc:295
logger(const char *name=0)
Definition: logger.cc:198
const string & ErrorColor()
Definition: logger.cc:32
static std::ostream * fOut
Definition: logger.cc:71
static ELevel filterMinimumLevel(ELevel level)
Definition: logger.cc:114
bool IsLevelEnabled(ELevel level) const
Definition: logger.cc:237
const string & DebugColor()
Definition: logger.cc:36
static std::shared_ptr< LoggerSet > AllLoggers()
Definition: logger.cc:45
const string & InfoColor()
Definition: logger.cc:34
#define COLOR_SUFFIX
Definition: logger.hh:53
void SetLevel(ELevel level) const
Definition: logger.cc:247
const string & WarnColor()
Definition: logger.cc:33
#define COLOR_FOREGROUND_GREEN
Definition: logger.hh:47
static tm * sProcessedTime
Definition: logger.cc:54
static logger::ELevel GetGlobalLevel()
Definition: logger.cc:260
static void SetOutStream(std::ostream *stream)
Definition: logger.cc:289
std::set< logger *> LoggerSet
Definition: logger.cc:44
#define COLOR_FOREGROUND_BLUE
Definition: logger.hh:49
#define COLOR_FOREGROUND_CYAN
Definition: logger.hh:50
#define COLOR_PREFIX
Definition: logger.hh:52
#define COLOR_FOREGROUND_RED
Definition: logger.hh:46
std::shared_ptr< Private > fPrivate
Definition: logger.hh:296
static void SetGlobalLevel(ELevel level)
Definition: logger.cc:266
#define COLOR_FOREGROUND_YELLOW
Definition: logger.hh:48
void logCout(ELevel level, const string &message, const Location &loc)
Definition: logger.cc:126
static std::mutex sMutex
Definition: logger.cc:42