Scarab  v3.2.1
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 LoggerSet* AllLoggers()
46  {
47  static LoggerSet* sAllLoggers = new LoggerSet();
48  return sAllLoggers;
49  }
50 
51  static char sDateTimeFormat[16];
52  static time_t sRawTime;
53  static tm* sProcessedTime;
54  static char sTimeBuff[512];
55  static size_t getTimeAbsoluteStr()
56  {
57  time(&logger::Private::sRawTime);
58 
59  sProcessedTime = localtime(&logger::Private::sRawTime);
60  return strftime(logger::Private::sTimeBuff, 512,
61  logger::Private::sDateTimeFormat,
62  logger::Private::sProcessedTime);
63  }
64 
65 
66  const char* fLogger;
67  static bool fColored;
69 
70  static std::ostream* fOut;
71  static std::ostream* fErr;
72 
73  static const char* level2Str(ELevel level)
74  {
75  switch(level)
76  {
77  case ELevel::eTrace : return "TRACE"; break;
78  case ELevel::eDebug : return "DEBUG"; break;
79  case ELevel::eInfo : return "INFO"; break;
80  case ELevel::eProg : return "PROG"; break;
81  case ELevel::eWarn : return "WARN"; break;
82  case ELevel::eError : return "ERROR"; break;
83  case ELevel::eFatal : return "FATAL"; break;
84  default : return "XXX";
85  }
86  }
87 
88  static string level2Color(ELevel level)
89  {
90  switch(level)
91  {
92  case ELevel::eTrace : return TraceColor(); break;
93  case ELevel::eDebug : return DebugColor(); break;
94  case ELevel::eInfo : return InfoColor(); break;
95  case ELevel::eProg : return ProgColor(); break;
96  case ELevel::eWarn : return WarnColor(); break;
97  case ELevel::eError : return ErrorColor(); break;
98  case ELevel::eFatal : return FatalColor(); break;
99  default : return OtherColor();
100  }
101  }
102 
103 
104  void logCout(ELevel level, const string& message, const Location& loc)
105  {
106  logger::Private::sMutex.lock();
107  logger::Private::getTimeAbsoluteStr();
108  if (fColored)
109  {
110  //cout << color << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << skKTEndColor << endl;
111  (*fOut) << Private::level2Color(level) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
112 #ifndef NDEBUG
113  (*fOut) << "(tid " << std::this_thread::get_id() << ") ";
114 #endif
115  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fOut));
116  (*fOut) << "(" << loc.fLineNumber << "): ";
117  (*fOut) << message << EndColor() << endl;
118  }
119  else
120  {
121  //cout << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << endl;
122  (*fOut) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
123 #ifndef NDEBUG
124  (*fOut) << "(tid " << std::this_thread::get_id() << ") ";
125 #endif
126  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fOut));
127  (*fOut) << "(" << loc.fLineNumber << "): ";
128  (*fOut) << message << endl;
129  }
130  logger::Private::sMutex.unlock();
131  }
132 
133  void logCerr(ELevel level, const string& message, const Location& loc)
134  {
135  logger::Private::sMutex.lock();
136  logger::Private::getTimeAbsoluteStr();
137  if (fColored)
138  {
139  //cout << color << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << skKTEndColor << endl;
140  (*fErr) << Private::level2Color(level) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
141 #ifndef NDEBUG
142  (*fErr) << "(tid " << std::this_thread::get_id() << ") ";
143 #endif
144  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fErr));
145  (*fErr) << "(" << loc.fLineNumber << "): ";
146  (*fErr) << message << EndColor() << endl;
147  }
148  else
149  {
150  //cout << KTLogger::Private::sTimeBuff << " [" << setw(5) << level << "] " << setw(16) << left << loc.fFileName << "(" << loc.fLineNumber << "): " << message << endl;
151  (*fErr) << logger::Private::sTimeBuff << " [" << setw(5) << Private::level2Str(level) << "] ";
152 #ifndef NDEBUG
153  (*fErr) << "(tid " << std::this_thread::get_id() << ") ";
154 #endif
155  copy(loc.fFileName.end() - std::min< int >(loc.fFileName.size(), 16), loc.fFileName.end(), ostream_iterator<char>(*fErr));
156  (*fErr) << "(" << loc.fLineNumber << "): ";
157  (*fErr) << message << endl;
158  }
159  logger::Private::sMutex.unlock();
160  }
161  };
162 
163  mutex logger::Private::sMutex;
164 
165  char logger::Private::sDateTimeFormat[16];
166  time_t logger::Private::sRawTime;
167  tm* logger::Private::sProcessedTime;
168  char logger::Private::sTimeBuff[512];
169 
170  bool logger::Private::fColored = true;
171 
172  std::ostream* logger::Private::fOut = &cout;
173  std::ostream* logger::Private::fErr = &cerr;
174 
175 
176  logger::logger(const char* name) : fPrivate(new Private())
177  {
178  if (name == 0)
179  {
180  fPrivate->fLogger = "root";
181  }
182  else
183  {
184  const char* logName = strrchr(name, '/') ? strrchr(name, '/') + 1 : name;
185  fPrivate->fLogger = logName;
186  }
187 #ifndef _WIN32
188  fPrivate->fColored = true;
189 #else
190  fPrivate->fColored = false;
191 #endif
192  sprintf(logger::Private::sDateTimeFormat, "%%Y-%%m-%%d %%T");
194  logger::Private::AllLoggers()->insert(this);
195  }
196 
197  logger::logger(const std::string& name) : fPrivate(new Private())
198  {
199  fPrivate->fLogger = name.c_str();
200 #ifndef _WIN32
201  fPrivate->fColored = true;
202 #else
203  fPrivate->fColored = false;
204 #endif
205  sprintf(logger::Private::sDateTimeFormat, "%%Y-%%m-%%d %%T");
207  logger::Private::AllLoggers()->insert(this);
208  }
209 
211  {
212  delete fPrivate;
213  }
214 
215  bool logger::IsLevelEnabled(ELevel level) const
216  {
217  return level >= fPrivate->fThreshold;
218  }
219 
221  {
222  return fPrivate->fThreshold;
223  }
224 
225  void logger::SetLevel(ELevel level) const
226  {
227 #if defined(NDEBUG) && defined(STANDARD)
228  fPrivate->fThreshold = level >= ELevel::eInfo ? level : ELevel::eInfo;
229 #elif defined(NDEBUG)
230  fPrivate->fThreshold = level >= ELevel::eProg ? level : ELevel::eProg;
231 #else
232  fPrivate->fThreshold = level;
233 #endif
234  }
235 
236  void logger::SetGlobalLevel(ELevel level) const
237  {
238  for( std::set< logger* >::iterator logIt = logger::Private::AllLoggers()->begin(); logIt != logger::Private::AllLoggers()->end(); ++logIt)
239  {
240  (*logIt)->SetLevel(level);
241  }
242  return;
243  }
244 
245  void logger::SetColored(bool flag)
246  {
247 #ifndef _WIN32
248  logger::Private::fColored = flag;
249 #else
250  std::cerr << "Colored logging is not enabled in Windows" << std::endl;
251 #endif
252  return;
253  }
254 
255  void logger::SetOutStream(std::ostream* stream)
256  {
257  logger::Private::fOut = stream;
258  return;
259  }
260 
261  void logger::SetErrStream(std::ostream* stream)
262  {
263  logger::Private::fErr = stream;
264  return;
265  }
266 
267  void logger::Log(ELevel level, const string& message, const Location& loc)
268  {
269  if (level >= ELevel::eWarn)
270  {
271  fPrivate->logCerr(level, message, loc);
272  }
273  else
274  {
275  fPrivate->logCout(level, message, loc);
276  }
277  }
278 }
std::string fFileName
Definition: logger.hh:141
#define COLOR_BRIGHT
Definition: logger.hh:45
ELevel GetLevel() const
Definition: logger.cc:220
const string & TraceColor()
Definition: logger.cc:37
const char * fLogger
Definition: logger.cc:66
const string & OtherColor()
Definition: logger.cc:38
const string & EndColor()
Definition: logger.cc:30
static LoggerSet * AllLoggers()
Definition: logger.cc:45
virtual ~logger()
Definition: logger.cc:210
void logCerr(ELevel level, const string &message, const Location &loc)
Definition: logger.cc:133
static time_t sRawTime
Definition: logger.cc:52
const string & FatalColor()
Definition: logger.cc:31
static bool fColored
Definition: logger.cc:67
static size_t getTimeAbsoluteStr()
Definition: logger.cc:55
#define COLOR_NORMAL
Definition: logger.hh:44
#define COLOR_SEPARATOR
Definition: logger.hh:54
void SetGlobalLevel(ELevel level) const
Definition: logger.cc:236
static std::ostream * fErr
Definition: logger.cc:71
STL namespace.
void Log(ELevel level, const std::string &message, const Location &loc=Location())
Definition: logger.cc:267
#define COLOR_FOREGROUND_WHITE
Definition: logger.hh:51
static void SetColored(bool flag)
Definition: logger.cc:245
Contains the logger class and macros, based on Kasper&#39;s KLogger class.
static const char * level2Str(ELevel level)
Definition: logger.cc:73
static string level2Color(ELevel level)
Definition: logger.cc:88
const string & ProgColor()
Definition: logger.cc:35
static void SetErrStream(std::ostream *stream)
Definition: logger.cc:261
logger(const char *name=0)
Definition: logger.cc:176
const string & ErrorColor()
Definition: logger.cc:32
static std::ostream * fOut
Definition: logger.cc:70
bool IsLevelEnabled(ELevel level) const
Definition: logger.cc:215
const string & DebugColor()
Definition: logger.cc:36
const string & InfoColor()
Definition: logger.cc:34
#define COLOR_SUFFIX
Definition: logger.hh:53
void SetLevel(ELevel level) const
Definition: logger.cc:225
const string & WarnColor()
Definition: logger.cc:33
#define COLOR_FOREGROUND_GREEN
Definition: logger.hh:47
static tm * sProcessedTime
Definition: logger.cc:53
static void SetOutStream(std::ostream *stream)
Definition: logger.cc:255
std::set< logger *> LoggerSet
Definition: logger.cc:44
Private * fPrivate
Definition: logger.hh:286
#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
#define COLOR_FOREGROUND_YELLOW
Definition: logger.hh:48
void logCout(ELevel level, const string &message, const Location &loc)
Definition: logger.cc:104
static std::mutex sMutex
Definition: logger.cc:42