1 |
|
|
/*************************************** |
2 |
|
|
Auteur : Pierre Aubert |
3 |
|
|
Mail : pierre.aubert@lapp.in2p3.fr |
4 |
|
|
Licence : CeCILL-C |
5 |
|
|
****************************************/ |
6 |
|
|
|
7 |
|
|
#include "convertToString.h" |
8 |
|
|
#include "string_filename.h" |
9 |
|
|
#include "string_system.h" |
10 |
|
|
|
11 |
|
|
#include "PLog.h" |
12 |
|
|
|
13 |
|
|
///Convert the log level into a string |
14 |
|
|
/** @param logLevel : log level to be converted |
15 |
|
|
* @return corresponding string |
16 |
|
|
*/ |
17 |
|
107 |
std::string phoenix_logLevelToStr(PLog::Level logLevel){ |
18 |
✓✓✓✓ ✓✓ |
107 |
switch(logLevel){ |
19 |
|
38 |
case PLog::INFO: |
20 |
✓ |
38 |
return "INFO"; |
21 |
|
5 |
case PLog::WARNING: |
22 |
✓ |
5 |
return "WARNING"; |
23 |
|
5 |
case PLog::ERROR: |
24 |
✓ |
5 |
return "ERROR"; |
25 |
|
5 |
case PLog::CRITICAL: |
26 |
✓ |
5 |
return "CRITICAL"; |
27 |
|
50 |
case PLog::ALWAYS: |
28 |
✓ |
50 |
return "ALWAYS"; |
29 |
|
4 |
default: |
30 |
✓ |
4 |
return "DEBUG"; |
31 |
|
|
} |
32 |
|
|
} |
33 |
|
|
|
34 |
|
|
///Convert a string into a log level |
35 |
|
|
/** @param str : string ot be converted |
36 |
|
|
* @return corresponding PLog::Level |
37 |
|
|
*/ |
38 |
|
6 |
PLog::Level phoenix_strToLogLevel(const std::string & str){ |
39 |
✓✓ |
6 |
if(str == "DEBUG"){return PLog::DEBUG;} |
40 |
✓✓ |
5 |
else if(str == "WARNING"){return PLog::WARNING;} |
41 |
✓✓ |
4 |
else if(str == "ERROR"){return PLog::ERROR;} |
42 |
✓✓ |
3 |
else if(str == "CRITICAL"){return PLog::CRITICAL;} |
43 |
✓✓ |
2 |
else if(str == "ALWAYS"){return PLog::ALWAYS;} |
44 |
|
1 |
else{return PLog::INFO;} |
45 |
|
|
} |
46 |
|
|
|
47 |
|
|
///Default constructor of PLog |
48 |
✓✓ |
12 |
PLog::PLog(){ |
49 |
✓ |
12 |
initialisationPLog(); |
50 |
|
12 |
} |
51 |
|
|
|
52 |
|
|
///Destructor of PLog |
53 |
|
32 |
PLog::~PLog(){ |
54 |
|
24 |
close(); |
55 |
|
24 |
clear(); |
56 |
✓✗ |
24 |
delete p_nullStream; |
57 |
|
32 |
} |
58 |
|
|
|
59 |
|
|
///Set the output filename of the current PLog |
60 |
|
|
/** @param fileName : output filename of the current PLog |
61 |
|
|
*/ |
62 |
|
11 |
void PLog::setFileName(const std::string & fileName){ |
63 |
|
11 |
p_fileName = fileName; |
64 |
|
11 |
} |
65 |
|
|
|
66 |
|
|
///Set the mode of the current PLog |
67 |
|
|
/** @param mode : mode of the current PLog |
68 |
|
|
*/ |
69 |
|
9 |
void PLog::setMode(PLog::Mode mode){ |
70 |
|
9 |
p_mode = mode; |
71 |
|
9 |
} |
72 |
|
|
|
73 |
|
|
///Set the log level of the current PLog |
74 |
|
|
/** @param logLevel : log level of the current PLog |
75 |
|
|
*/ |
76 |
|
6 |
void PLog::setLogLevel(PLog::Level logLevel){ |
77 |
|
6 |
p_logLevel = logLevel; |
78 |
|
6 |
} |
79 |
|
|
|
80 |
|
|
///Set the thread index of the current PLog |
81 |
|
|
/** @param threadIndex : thread index of the current PLog |
82 |
|
|
*/ |
83 |
|
2 |
void PLog::setThreadIndex(size_t threadIndex){ |
84 |
|
2 |
p_threadIndex = threadIndex; |
85 |
|
2 |
} |
86 |
|
|
|
87 |
|
|
///Resize the number of cihldren log file |
88 |
|
|
/** @param nbThread : number of sub log files to be created (typically the number of threads of a program) |
89 |
|
|
*/ |
90 |
|
1 |
void PLog::resize(size_t nbThread){ |
91 |
✓ |
1 |
clear(); |
92 |
✓ |
1 |
p_vecLog.resize(nbThread); |
93 |
✓ |
2 |
std::string baseFileName(eraseExtension(p_fileName)); |
94 |
✓ |
2 |
std::string extention(getExtention(p_fileName)); |
95 |
✓✓ |
5 |
for(size_t i(0lu); i < nbThread; ++i){ |
96 |
✓✓ |
4 |
p_vecLog[i] = new PLog; |
97 |
✓✓✓✓ ✓✓ |
4 |
p_vecLog[i]->setFileName(baseFileName + "_" + convertToString(i) + "." + extention); |
98 |
✓ |
4 |
p_vecLog[i]->setMode(p_mode); |
99 |
✓ |
4 |
p_vecLog[i]->setLogLevel(p_logLevel); |
100 |
|
|
} |
101 |
|
1 |
} |
102 |
|
|
|
103 |
|
|
///Open the current PLog and its children |
104 |
|
|
/** @return true on success, false otherwise |
105 |
|
|
*/ |
106 |
|
12 |
bool PLog::open(){ |
107 |
|
12 |
bool b(true); |
108 |
|
12 |
b &= streamOpen(); |
109 |
|
12 |
p_isOpen = b; |
110 |
✓✗ |
12 |
if(b){ |
111 |
|
12 |
getLogAlways() << "[UTC][Date][ThreadIndex][LogLevel] : log message" << std::endl; |
112 |
✓✓ |
12 |
getLogAlways() << "Start logging at " << phoenix_getDate() << std::endl; |
113 |
✓✓✓ |
12 |
getLogAlways() << "Current logging level '"<<phoenix_logLevelToStr(getLogLevel())<<"'" << std::endl; |
114 |
|
|
} |
115 |
✓✓ |
16 |
for(std::vector<PLog*>::iterator it(p_vecLog.begin()); it != p_vecLog.end(); ++it){ |
116 |
|
4 |
PLog* log = *it; |
117 |
✓✗ |
4 |
if(log != NULL){ |
118 |
✓ |
4 |
b &= log->open(); |
119 |
|
|
} |
120 |
|
|
} |
121 |
|
12 |
return b; |
122 |
|
|
} |
123 |
|
|
|
124 |
|
|
///Close the current PLog and its children |
125 |
|
21 |
void PLog::close(){ |
126 |
✓✓✓✗
|
21 |
if(p_stream != NULL && p_isOpen){ |
127 |
✓✓ |
12 |
getLogAlways() << "Close Log File at " << phoenix_getDate() << std::endl; |
128 |
|
|
} |
129 |
✓✓ |
21 |
if(p_logFile.is_open()){ |
130 |
|
9 |
p_logFile.close(); |
131 |
|
|
} |
132 |
|
|
// if(p_mode == PLog::STRING_ONLY){ |
133 |
|
|
// p_logString.close(); |
134 |
|
|
// } |
135 |
✓✓ |
21 |
if(p_oldStdCerrBuffer != NULL){ |
136 |
|
2 |
std::cerr.rdbuf(p_oldStdCerrBuffer); //Let's get back to previous std::cerr buffer |
137 |
|
|
} |
138 |
✓✓ |
21 |
if(p_oldStdCoutBuffer != NULL){ |
139 |
|
2 |
std::cout.rdbuf(p_oldStdCoutBuffer); //Let's get back to previous std::cout buffer |
140 |
|
|
} |
141 |
✓✓ |
21 |
if(p_stream != NULL){ |
142 |
✓✗ |
12 |
delete p_stream; |
143 |
|
12 |
p_stream = NULL; |
144 |
|
|
} |
145 |
|
21 |
p_isOpen = false; |
146 |
✓✓ |
25 |
for(std::vector<PLog*>::iterator it(p_vecLog.begin()); it != p_vecLog.end(); ++it){ |
147 |
|
4 |
PLog* log = *it; |
148 |
✓✗ |
4 |
if(log != NULL){ |
149 |
✓ |
4 |
log->close(); |
150 |
|
|
} |
151 |
|
|
} |
152 |
|
21 |
} |
153 |
|
|
|
154 |
|
|
///Clear the children of the current PLog |
155 |
|
13 |
void PLog::clear(){ |
156 |
✓✓ |
13 |
if(p_vecLog.size() != 0lu){ |
157 |
✓✓ |
5 |
for(std::vector<PLog*>::iterator it(p_vecLog.begin()); it != p_vecLog.end(); ++it){ |
158 |
|
4 |
PLog* log = *it; |
159 |
✓✗ |
4 |
if(log != NULL){ |
160 |
✓✗ |
4 |
delete log; |
161 |
|
|
} |
162 |
|
|
} |
163 |
|
1 |
p_vecLog.clear(); |
164 |
|
|
} |
165 |
|
13 |
} |
166 |
|
|
|
167 |
|
|
///Append the log (STRING_ONLY mode) into an other log |
168 |
|
|
/** @param str : log string to be appended |
169 |
|
|
*/ |
170 |
|
1 |
void PLog::appendLog(std::stringstream & str){ |
171 |
✓ |
1 |
getLog(PLog::ALWAYS) << "Append log" << std::endl << str.str(); |
172 |
|
1 |
} |
173 |
|
|
|
174 |
|
|
///Get the PLog at given index |
175 |
|
|
/** @return PLog at Index |
176 |
|
|
*/ |
177 |
|
4 |
PLog & PLog::getLog(size_t threadIndex){ |
178 |
|
4 |
return *(p_vecLog[threadIndex]); |
179 |
|
|
} |
180 |
|
|
|
181 |
|
|
///Get the current log file |
182 |
|
|
/** @return current log file |
183 |
|
|
*/ |
184 |
|
|
std::ofstream & PLog::getLogFile(){ |
185 |
|
|
return p_logFile; |
186 |
|
|
} |
187 |
|
|
|
188 |
|
|
///Get the log string |
189 |
|
|
/** @return log string |
190 |
|
|
*/ |
191 |
|
1 |
std::stringstream & PLog::getLogString(){ |
192 |
|
1 |
return p_logString; |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
///Write log into the PLog |
196 |
|
|
/** @param logLevel : log level of the current line |
197 |
|
|
* @return ofstream to be written |
198 |
|
|
*/ |
199 |
|
91 |
std::ostream & PLog::getLog(PLog::Level logLevel){ |
200 |
✓✓ |
91 |
if(logLevel >= p_logLevel){ |
201 |
✓✓✓✓ ✓✓✓ |
89 |
*p_stream << "[" << phoenix_getTime() << "][" << phoenix_getDateCompact() << "][" << p_threadIndex << "]["<<phoenix_logLevelToStr(logLevel)<<"] : "; |
202 |
|
89 |
return *p_stream; |
203 |
|
|
}else{ |
204 |
|
2 |
return *p_nullStream; |
205 |
|
|
} |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
///Write debug message into the PLog |
209 |
|
|
/** @return ofstream to be written |
210 |
|
|
*/ |
211 |
|
2 |
std::ostream & PLog::getLogDebug(){ |
212 |
|
2 |
return getLog(PLog::DEBUG); |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
///Write info message into the PLog |
216 |
|
|
/** @return ofstream to be written |
217 |
|
|
*/ |
218 |
|
6 |
std::ostream & PLog::getLogInfo(){ |
219 |
|
6 |
return getLog(PLog::INFO); |
220 |
|
|
} |
221 |
|
|
|
222 |
|
|
///Write warning message into the PLog |
223 |
|
|
/** @return ofstream to be written |
224 |
|
|
*/ |
225 |
|
2 |
std::ostream & PLog::getLogWarning(){ |
226 |
|
2 |
return getLog(PLog::WARNING); |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
///Write error message into the PLog |
230 |
|
|
/** @return ofstream to be written |
231 |
|
|
*/ |
232 |
|
2 |
std::ostream & PLog::getLogError(){ |
233 |
|
2 |
return getLog(PLog::ERROR); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
|
///Write critical message into the PLog |
237 |
|
|
/** @return ofstream to be written |
238 |
|
|
*/ |
239 |
|
2 |
std::ostream & PLog::getLogCritical(){ |
240 |
|
2 |
return getLog(PLog::CRITICAL); |
241 |
|
|
} |
242 |
|
|
|
243 |
|
|
///Write always message into the PLog |
244 |
|
|
/** @return ofstream to be written |
245 |
|
|
*/ |
246 |
|
48 |
std::ostream & PLog::getLogAlways(){ |
247 |
|
48 |
return getLog(PLog::ALWAYS); |
248 |
|
|
} |
249 |
|
|
|
250 |
|
|
|
251 |
|
|
///Get the filename of the current log |
252 |
|
|
/** @return filename of the current log |
253 |
|
|
*/ |
254 |
|
2 |
const std::string & PLog::getFileName() const{ |
255 |
|
2 |
return p_fileName; |
256 |
|
|
} |
257 |
|
|
|
258 |
|
|
///Get the mode of the current PLog |
259 |
|
|
/** @return mode of the current PLog |
260 |
|
|
*/ |
261 |
|
|
PLog::Mode PLog::getMode() const{ |
262 |
|
|
return p_mode; |
263 |
|
|
} |
264 |
|
|
|
265 |
|
|
///Get the log level of the current PLog |
266 |
|
|
/** @return log level of the current PLog |
267 |
|
|
*/ |
268 |
|
12 |
PLog::Level PLog::getLogLevel() const{ |
269 |
|
12 |
return p_logLevel; |
270 |
|
|
} |
271 |
|
|
|
272 |
|
|
///Get the thread index of the current PLog |
273 |
|
|
/** @return thread index of the current PLog |
274 |
|
|
*/ |
275 |
|
1 |
size_t PLog::getThreadIndex() const{ |
276 |
|
1 |
return p_threadIndex; |
277 |
|
|
} |
278 |
|
|
|
279 |
|
|
///Initialisation function of the class PLog |
280 |
|
12 |
void PLog::initialisationPLog(){ |
281 |
|
12 |
p_mode = PLog::FILE_ONLY; |
282 |
|
12 |
p_logLevel = PLog::INFO; |
283 |
|
12 |
p_oldStdCerrBuffer = NULL; |
284 |
|
12 |
p_oldStdCoutBuffer = NULL; |
285 |
|
12 |
p_isOpen = false; |
286 |
|
12 |
p_stream = NULL; |
287 |
✓ |
12 |
p_nullStream = new std::ostream(NULL); |
288 |
|
12 |
p_threadIndex = 0lu; |
289 |
|
12 |
} |
290 |
|
|
|
291 |
|
|
///Allocate the stream |
292 |
|
|
/** @param buffer : buffer to be used |
293 |
|
|
*/ |
294 |
|
12 |
void PLog::allocateStream(std::streambuf* buffer){ |
295 |
✗✓ |
12 |
if(p_stream != NULL){ |
296 |
|
|
delete p_stream; |
297 |
|
|
} |
298 |
✓ |
12 |
p_stream = new std::ostream(buffer); |
299 |
|
12 |
} |
300 |
|
|
|
301 |
|
|
///Open the streams |
302 |
|
|
/** @return true on success, false otherwise |
303 |
|
|
*/ |
304 |
|
12 |
bool PLog::streamOpen(){ |
305 |
|
12 |
bool b(true); |
306 |
✓✓ |
12 |
if(p_mode == PLog::FILE_ONLY){ |
307 |
|
8 |
p_logFile.open(p_fileName); |
308 |
|
8 |
b &= p_logFile.is_open(); |
309 |
✓✗ |
8 |
if(b){ |
310 |
|
8 |
allocateStream(p_logFile.rdbuf()); |
311 |
|
|
} |
312 |
✓✓ |
4 |
}else if(p_mode == PLog::STRING_ONLY){ |
313 |
|
1 |
std::cerr << "PLog::streamOpen : p_logString.rdbuf() = " << p_logString.rdbuf() << std::endl; |
314 |
|
1 |
allocateStream(p_logString.rdbuf()); |
315 |
✓✓ |
3 |
}else if(p_mode == PLog::FILE_CAPTURE_STDOUT_STDERR){ |
316 |
|
1 |
p_logFile.open(p_fileName); |
317 |
|
1 |
b &= p_logFile.is_open(); |
318 |
✓✗ |
1 |
if(b){ |
319 |
|
1 |
p_oldStdCerrBuffer = std::cerr.rdbuf(p_logFile.rdbuf()); |
320 |
|
1 |
p_oldStdCoutBuffer = std::cout.rdbuf(p_logFile.rdbuf()); |
321 |
|
1 |
allocateStream(p_logFile.rdbuf()); |
322 |
|
|
} |
323 |
✓✓ |
2 |
}else if(p_mode == PLog::STDOUT_ONLY){ |
324 |
|
1 |
allocateStream(std::cout.rdbuf()); |
325 |
✓✗ |
1 |
}else if(p_mode == PLog::DISABLE){ |
326 |
|
1 |
allocateStream(NULL); |
327 |
|
|
} |
328 |
|
12 |
return b; |
329 |
|
|
} |
330 |
|
|
|
331 |
|
|
|
332 |
|
|
|
333 |
|
|
|