Scarab  v2.4.9
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 eTrace : return "TRACE"; break;
78  case eDebug : return "DEBUG"; break;
79  case eInfo : return "INFO"; break;
80  case eProg : return "PROG"; break;
81  case eWarn : return "WARN"; break;
82  case eError : return "ERROR"; break;
83  case eFatal : return "FATAL"; break;
84  default : return "XXX";
85  }
86  }
87 
88  static string level2Color(ELevel level)
89  {
90  switch(level)
91  {
92  case eTrace : return TraceColor(); break;
93  case eDebug : return DebugColor(); break;
94  case eInfo : return InfoColor(); break;
95  case eProg : return ProgColor(); break;
96  case eWarn : return WarnColor(); break;
97  case eError : return ErrorColor(); break;
98  case 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");
193  SetLevel(eDebug);
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");
206  SetLevel(eDebug);
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 
220  void logger::SetLevel(ELevel level) const
221  {
222 #if defined(NDEBUG) && defined(STANDARD)
223  fPrivate->fThreshold = level >= eInfo ? level : eInfo;
224 #elif defined(NDEBUG)
225  fPrivate->fThreshold = level >= eProg ? level : eProg;
226 #else
227  fPrivate->fThreshold = level;
228 #endif
229  }
230 
231  void logger::SetGlobalLevel(ELevel level) const
232  {
233  for( std::set< logger* >::iterator logIt = logger::Private::AllLoggers()->begin(); logIt != logger::Private::AllLoggers()->end(); ++logIt)
234  {
235  (*logIt)->SetLevel(level);
236  }
237  return;
238  }
239 
240  void logger::SetColored(bool flag)
241  {
242 #ifndef _WIN32
243  logger::Private::fColored = flag;
244 #else
245  std::cerr << "Colored logging is not enabled in Windows" << std::endl;
246 #endif
247  return;
248  }
249 
250  void logger::SetOutStream(std::ostream* stream)
251  {
252  logger::Private::fOut = stream;
253  return;
254  }
255 
256  void logger::SetErrStream(std::ostream* stream)
257  {
258  logger::Private::fErr = stream;
259  return;
260  }
261 
262  void logger::Log(ELevel level, const string& message, const Location& loc)
263  {
264  if (level >= eWarn)
265  {
266  fPrivate->logCerr(level, message, loc);
267  }
268  else
269  {
270  fPrivate->logCout(level, message, loc);
271  }
272  }
273 }
std::string fFileName
Definition: logger.hh:135
#define COLOR_BRIGHT
Definition: logger.hh:45
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:231
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:262
#define COLOR_FOREGROUND_WHITE
Definition: logger.hh:51
static void SetColored(bool flag)
Definition: logger.cc:240
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:256
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:220
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:250
std::set< logger *> LoggerSet
Definition: logger.cc:44
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:104
static std::mutex sMutex
Definition: logger.cc:42