QwAnalysis
QwLog.cc
Go to the documentation of this file.
1 /*!
2  * \file QwLog.cc
3  * \brief A logfile class, based on an identical class in the Hermes analyzer
4  *
5  * \author Wouter Deconinck
6  * \date 2009-11-25
7  */
8 
9 #include "QwLog.h"
10 
11 // System headers
12 #include <fstream>
13 
14 // Boost headers
15 #include <boost/regex.hpp>
16 
17 // Qweak headers
18 #include "QwColor.h"
19 #include "QwOptions.h"
20 
21 // Create the static logger object (with streams to screen and file)
23 
24 // Set the static flags
25 bool QwLog::fScreenAtNewLine = true;
26 bool QwLog::fScreenInColor = false;
27 bool QwLog::fFileAtNewLine = true;
28 
29 // Log file open modes
30 const std::ios_base::openmode QwLog::kTruncate = std::ios::trunc;
31 const std::ios_base::openmode QwLog::kAppend = std::ios::app;
32 
33 /*! The constructor initializes the screen stream and resets the file stream
34  */
36 : std::ostream(std::cout.rdbuf())
37 {
39  fScreen = &std::cout;
40 
42  fFile = 0;
43 
45 
46  fUseColor = true;
47 
49 }
50 
51 /*! The destructor destroys the log file, if it was present
52  */
54 {
55  if (fFile) {
56  delete fFile;
57  fFile = 0;
58  }
59 }
60 
61 
62 /**
63  * Defines configuration options for logging class using QwOptions
64  * functionality.
65  *
66  * Note: this uses a pointer as opposed to a reference, because as indicated
67  * above the QwLog class cannot depend on the QwOptions class. When using a
68  * pointer we only need a forward declaration and we do not need to include
69  * the header file QwOptions.h.
70  *
71  * @param options Options object
72  */
74 {
75  // Define the logging options
76  options->AddOptions("Logging options")("QwLog.color",
77  po::value<bool>()->default_value(true),
78  "colored screen output");
79  options->AddOptions("Logging options")("QwLog.logfile",
80  po::value<string>(),
81  "log file");
82  options->AddOptions("Logging options")("QwLog.loglevel-file",
83  po::value<int>()->default_value(kMessage),
84  "log level for file output");
85  options->AddOptions("Logging options")("QwLog.loglevel-screen",
86  po::value<int>()->default_value(kMessage),
87  "log level for screen output");
88  options->AddOptions("Logging options")("QwLog.print-signature",
89  po::value<bool>()->default_bool_value(false),
90  "print signature on error or warning");
91  options->AddOptions("Logging options")("QwLog.debug-function",
92  po::value< std::vector<string> >()->multitoken(),
93  "print debugging output of function with signatures satisfying the specified regex");
94 }
95 
96 
97 /**
98  * Process configuration options for logging class using QwOptions
99  * functionality.
100  *
101  * Note: this uses a pointer as opposed to a reference, because as indicated
102  * above the QwLog class cannot depend on the QwOptions class. When using a
103  * pointer we only need a forward declaration and we do not need to include
104  * the header file QwOptions.h.
105  *
106  * @param options Options object
107  */
109 {
110  // Initialize log file
111  if (options->HasValue("QwLog.logfile"))
112  InitLogFile(options->GetValue<std::string>("QwLog.logfile"));
113 
114  // Set the logging thresholds
115  SetFileThreshold(options->GetValue<int>("QwLog.loglevel-file"));
116  SetScreenThreshold(options->GetValue<int>("QwLog.loglevel-screen"));
117 
118  // Set color flag
119  SetScreenColor(options->GetValue<bool>("QwLog.color"));
120 
121  // Set the flags for function name and signature printing
122  fPrintFunctionSignature = options->GetValue<bool>("QwLog.print-signature");
123 
124  // Set the list of regular expressions for functions to debug
125  fDebugFunctionRegexString = options->GetValueVector<std::string>("QwLog.debug-function");
126  if (fDebugFunctionRegexString.size() > 0)
127  std::cout << "Debug regex list:" << std::endl;
128  for (size_t i = 0; i < fDebugFunctionRegexString.size(); i++) {
129  std::cout << fDebugFunctionRegexString.back() << std::endl;
130  }
131 }
132 
133 
134 /*!
135  * Determine whether the function name matches a specified list of regular expressions
136  */
137 bool QwLog::IsDebugFunction(const string func_sig)
138 {
139  // If not in our cached list
140  if (fIsDebugFunction.find(func_sig) == fIsDebugFunction.end()) {
141  // Look through all regexes
142  fIsDebugFunction[func_sig] = false;
143  for (size_t i = 0; i < fDebugFunctionRegexString.size(); i++) {
144  // When we find a match, cache it and break out
146  if (boost::regex_match(func_sig, regex)) {
147  fIsDebugFunction[func_sig] = true;
148  break;
149  }
150  }
151  }
152  return fIsDebugFunction[func_sig];
153 }
154 
155 /*! Initialize the log file with name 'name'
156  */
157 void QwLog::InitLogFile(const string name, const std::ios_base::openmode mode)
158 {
159  if (fFile) {
160  delete fFile;
161  fFile = 0;
162  }
163 
164  std::ios_base::openmode flags = std::ios::out | mode;
165  fFile = new std::ofstream(name.c_str(), flags);
167 }
168 
169 /*! Set the screen color mode
170  */
171 void QwLog::SetScreenColor(bool flag)
172 {
173  fUseColor = flag;
174 }
175 
176 /*! Set the screen log level
177  */
179 {
181 }
182 
183 /*! Set the file log level
184  */
186 {
187  fFileThreshold = QwLogLevel(thr);
188 }
189 
190 /*! Set the stream log level
191  */
193  const QwLogLevel level,
194  const std::string func_sig)
195 {
196  // Set the log level of this sink
197  fLogLevel = level;
198 
199  // Override log level of this sink when in a debugged function
200  if (IsDebugFunction(func_sig)) fLogLevel = QwLog::kAlways;
201 
202  if (fScreen && fLogLevel <= fScreenThreshold) {
203  if (fScreenAtNewLine) {
204  // Put something at the beginning of a new line
205  switch (level) {
206  case kError:
207  if (fUseColor) {
208  *(fScreen) << QwColor(Qw::kRed);
209  fScreenInColor = true;
210  }
212  *(fScreen) << "Error (in " << func_sig << "): ";
213  else
214  *(fScreen) << "Error: ";
215  break;
216  case kWarning:
217  if (fUseColor) {
218  *(fScreen) << QwColor(Qw::kRed);
219  fScreenInColor = true;
220  }
222  *(fScreen) << "Warning (in " << func_sig << "): ";
223  else
224  *(fScreen) << "Warning: ";
225  if (fUseColor) {
226  *(fScreen) << QwColor(Qw::kNormal);
227  fScreenInColor = false;
228  }
229  break;
230  default:
231  fScreenInColor = false;
232  break;
233  }
234  }
235  fScreenAtNewLine = false;
236  }
237 
238  if (fFile && fLogLevel <= fFileThreshold) {
239  if (fFileAtNewLine) {
240  *(fFile) << GetTime();
241  switch (level) {
242  case kError: *(fFile) << " EE"; break;
243  case kWarning: *(fFile) << " WW"; break;
244  case kMessage: *(fFile) << " MM"; break;
245  case kVerbose: *(fFile) << " VV"; break;
246  case kDebug: *(fFile) << " DD"; break;
247  default: *(fFile) << " "; break;
248  }
249  *(fFile) << " - ";
250  fFileAtNewLine = false;
251  }
252  }
253 
254  return *this;
255 }
256 
257 #if (__GNUC__ >= 3)
258 /*!
259  */
260 QwLog& QwLog::operator<<(std::ios_base& (*manip) (std::ios_base&))
261 {
263  *(fScreen) << manip;
264  }
265 
266 // The following solution leads to double calls to QwLog::endl
267 // if (fScreen && fLogLevel <= fScreenThreshold) {
268 // *(fScreen) << manip;
269 // }
270 // if (fFile && fLogLevel <= fFileThreshold) {
271 // *(fFile) << manip;
272 // }
273 
274  return *this;
275 }
276 #endif
277 
278 /*!
279  */
280 QwLog& QwLog::operator<<(std::ostream& (*manip) (std::ostream&))
281 {
283  *(fScreen) << manip;
284  }
285 
286 // The following solution leads to double calls to QwLog::endl
287 // if (fScreen && fLogLevel <= fScreenThreshold) {
288 // *(fScreen) << manip;
289 // }
290 // if (fFile && fLogLevel <= fFileThreshold) {
291 // *(fFile) << manip;
292 // }
293 
294  return *this;
295 }
296 
297 /*! End of the line
298  */
299 std::ostream& QwLog::endl(std::ostream& strm)
300 {
301  if (gQwLog.fScreen && gQwLog.fLogLevel <= gQwLog.fScreenThreshold) {
302  if (fScreenInColor)
303  *(gQwLog.fScreen) << QwColor(Qw::kNormal) << std::endl;
304  else
305  *(gQwLog.fScreen) << std::endl;
306  fScreenAtNewLine = true;
307  fScreenInColor = false;
308  }
309  if (gQwLog.fFile && gQwLog.fLogLevel <= gQwLog.fFileThreshold) {
310  *(gQwLog.fFile) << std::endl;
311  fFileAtNewLine = true;
312  }
313 
314  return strm;
315 }
316 
317 /*! Flush the streams
318  */
319 std::ostream& QwLog::flush(std::ostream& strm)
320 {
321  if (gQwLog.fScreen) {
322  *(gQwLog.fScreen) << std::flush;
323  }
324  if (gQwLog.fFile) {
325  *(gQwLog.fFile) << std::flush;
326  }
327  return strm;
328 }
329 
330 /*! Get the local time
331  */
332 const char* QwLog::GetTime()
333 {
334  time_t now = time(0);
335  if (now >= 0) {
336  struct tm *currentTime = localtime(&now);
337  strftime(fTimeString, 128, "%Y-%m-%d, %T", currentTime);
338  return fTimeString;
339  } else {
340  return "";
341  }
342 }
void InitLogFile(const std::string name, const std::ios_base::openmode mode=kAppend)
Initialize the log file with name &#39;name&#39;.
Definition: QwLog.cc:157
std::vector< std::string > fDebugFunctionRegexString
Definition: QwLog.h:187
QwLogLevel fFileThreshold
File thresholds and stream.
Definition: QwLog.h:177
#define default_bool_value(b)
Definition: QwOptions.h:51
static bool fScreenAtNewLine
Definition: QwLog.h:195
void SetScreenThreshold(int thr)
Set the screen log level.
Definition: QwLog.cc:178
A logfile class.
Definition: QwLog.h:78
An options class.
Definition: QwOptions.h:133
bool HasValue(const std::string &key)
Has this key been defined.
Definition: QwOptions.h:233
static bool fFileAtNewLine
Flags only relevant for current line, but static for use in static function.
Definition: QwLog.h:193
QwLogLevel fScreenThreshold
Screen thresholds and stream.
Definition: QwLog.h:174
std::vector< T > GetValueVector(const std::string &key)
Get a list of templated values.
Definition: QwOptions.h:253
QwLog()
The constructor.
Definition: QwLog.cc:35
std::ostream * fScreen
Definition: QwLog.h:175
static const std::ios_base::openmode kAppend
Definition: QwLog.h:104
void ProcessOptions(QwOptions *options)
Process class options for QwOptions.
Definition: QwLog.cc:108
QwLog & operator<<(const T &t)
Stream an object to the output stream.
Definition: QwLog.h:141
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition: QwOptions.h:164
static const std::ios_base::openmode kTruncate
Log file open modes.
Definition: QwLog.h:103
char fTimeString[128]
Definition: QwLog.h:171
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
void SetScreenColor(bool flag)
Set the screen color mode.
Definition: QwLog.cc:171
const char * GetTime()
Get the local time.
Definition: QwLog.cc:332
void SetFileThreshold(int thr)
Set the file log level.
Definition: QwLog.cc:185
QwLogLevel
Loglevels.
Definition: QwLog.h:93
virtual ~QwLog()
The destructor.
Definition: QwLog.cc:53
std::map< std::string, bool > fIsDebugFunction
List of regular expressions for functions that will have increased log level.
Definition: QwLog.h:186
A logfile class, based on an identical class in the Hermes analyzer.
bool fPrintFunctionSignature
Flag to print function signature on warning or error.
Definition: QwLog.h:183
static void DefineOptions(QwOptions *options)
Define available class options for QwOptions.
Definition: QwLog.cc:73
QwLogLevel fLogLevel
Log level of this stream.
Definition: QwLog.h:180
regex
Definition: CMakeCache.txt:395
QwLog & operator()(const QwLogLevel level, const std::string func_sig="<unknown>")
Set the stream log level.
Definition: QwLog.cc:192
std::ostream * fFile
Definition: QwLog.h:178
A color changing class for the output stream.
Definition: QwColor.h:98
bool fUseColor
Flag to disable color.
Definition: QwLog.h:190
static bool fScreenInColor
Definition: QwLog.h:194
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
An options class which parses command line, config file and environment.
bool IsDebugFunction(const string func_name)
Determine whether the function name matches a specified list of regular expressions.
Definition: QwLog.cc:137
usr bin c fPIC std
QwLog gQwLog
Definition: QwLog.cc:22
static std::ostream & flush(std::ostream &)
Flush the streams.
Definition: QwLog.cc:319