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