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