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