1 /*
2 * Open BEAGLE
3 * Copyright (C) 2001-2007 by Christian Gagne and Marc Parizeau
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Contact:
20 * Laboratoire de Vision et Systemes Numeriques
21 * Departement de genie electrique et de genie informatique
22 * Universite Laval, Quebec, Canada, G1K 7P4
23 * http://vision.gel.ulaval.ca
24 *
25 */
26
27 /*!
28 * \file beagle/src/LoggerXML.cpp
29 * \brief Implementation of class LoggerXML.
30 * \author Christian Gagne
31 * \author Marc Parizeau
32 * $Revision: 1.16.2.2 $
33 * $Date: 2007/09/10 18:24:12 $
34 */
35
36 #include "beagle/Beagle.hpp"
37
38 #include <cstdio>
39 #include <iomanip>
40 #include <fstream>
41
42 using namespace Beagle;
43
44 /*!
45 * \brief Construct a new LoggerXML.
46 */
LoggerXML()47 LoggerXML::LoggerXML() :
48 mActualFileName(""),
49 mStreamerFile(NULL),
50 mLogOutStream(NULL),
51 mStreamerConsole(NULL),
52 mTerminated(false)
53 { }
54
55
56 /*!
57 * \brief Copy construct a LoggerXML is undefined.
58 */
LoggerXML(const LoggerXML & inLoggerXML)59 LoggerXML::LoggerXML(const LoggerXML& inLoggerXML) :
60 Logger()
61 {
62 Beagle_StackTraceBeginM();
63 throw Beagle_UndefinedMethodInternalExceptionM("LoggerXML(const LoggerXML&)", "LoggerXML", getName());
64 Beagle_StackTraceEndM("LoggerXML::LoggerXML(const LoggerXML& inLoggerXML)");
65 }
66
67
68 /*!
69 * \brief Destruct a LoggerXML.
70 */
~LoggerXML()71 LoggerXML::~LoggerXML()
72 {
73 Beagle_StackTraceBeginM();
74 terminate();
75 Beagle_StackTraceEndM("LoggerXML::~LoggerXML()");
76 }
77
78
79 /*!
80 * \brief Copy a LoggerXML is undefined.
81 */
operator =(const LoggerXML & inLoggerXML)82 LoggerXML& LoggerXML::operator=(const LoggerXML& inLoggerXML)
83 {
84 Beagle_StackTraceBeginM();
85 throw Beagle_UndefinedMethodInternalExceptionM("operator=","LoggerXML",getName());
86 Beagle_StackTraceEndM("LoggerXML& LoggerXML::operator=(const LoggerXML& inLoggerXML)");
87 }
88
89
90 /*!
91 * \brief Initialize logger by registering its parameters.
92 * \param ioSystem Reference to the system to use for initialization.
93 */
initialize(System & ioSystem)94 void LoggerXML::initialize(System& ioSystem)
95 {
96 Beagle_StackTraceBeginM();
97 Logger::initialize(ioSystem);
98
99 if(ioSystem.getRegister().isRegistered("lg.console.level")) {
100 mLogConsoleLevel = castHandleT<UInt>(ioSystem.getRegister().getEntry("lg.console.level"));
101 } else {
102 mLogConsoleLevel = new UInt(eStats);
103 string lLongDescrip("Log level used for console output generation. ");
104 lLongDescrip += "Log levels available are: (0) no log, (1) basic logs, (2) stats, ";
105 lLongDescrip += "(3) general informations, (4) details on operations, ";
106 lLongDescrip += "(5) trace of the algorithms, (6) verbose, ";
107 lLongDescrip += "(7) debug (enabled only in full debug mode).";
108 Register::Description lDescription(
109 "Console log level",
110 "UInt",
111 "2",
112 lLongDescrip
113 );
114 ioSystem.getRegister().addEntry("lg.console.level", mLogConsoleLevel, lDescription);
115 }
116
117 if(ioSystem.getRegister().isRegistered("lg.file.level")) {
118 mLogFileLevel = castHandleT<UInt>(ioSystem.getRegister().getEntry("lg.file.level"));
119 } else {
120 mLogFileLevel = new UInt(eInfo);
121 string lLongDescrip("Log level used for file output generation. ");
122 lLongDescrip += "Log levels available are: (0) no log, (1) basic logs, (2) stats, ";
123 lLongDescrip += "(3) general informations, (4) details on operations, ";
124 lLongDescrip += "(5) trace of the algorithms, (6) verbose, ";
125 lLongDescrip += "(7) debug (enabled only in full debug mode).";
126 Register::Description lDescription(
127 "File log level",
128 "UInt",
129 "3",
130 lLongDescrip
131 );
132 ioSystem.getRegister().addEntry("lg.file.level", mLogFileLevel, lDescription);
133 }
134
135 if(ioSystem.getRegister().isRegistered("lg.file.name")) {
136 mLogFileName = castHandleT<String>(ioSystem.getRegister().getEntry("lg.file.name"));
137 } else {
138 mLogFileName = new String("beagle.log");
139 string lLongDescrip("Filename in which messages are outputed. ");
140 lLongDescrip += "An empty string file name means no output is done to a file.";
141 Register::Description lDescription(
142 "Log filename",
143 "String",
144 "\"beagle.log\"",
145 lLongDescrip
146 );
147 ioSystem.getRegister().addEntry("lg.file.name", mLogFileName, lDescription);
148 }
149
150 if(ioSystem.getRegister().isRegistered("lg.show.level")) {
151 mShowLevel = castHandleT<Bool>(ioSystem.getRegister().getEntry("lg.show.level"));
152 } else {
153 mShowLevel = new Bool(false);
154 string lLongDescrip("Flag whether logging level in outputed in the logs.");
155 Register::Description lDescription(
156 "Show level in logs",
157 "Bool",
158 "0",
159 lLongDescrip
160 );
161 ioSystem.getRegister().addEntry("lg.show.level", mShowLevel, lDescription);
162 }
163
164 if(ioSystem.getRegister().isRegistered("lg.show.type")) {
165 mShowType = castHandleT<Bool>(ioSystem.getRegister().getEntry("lg.show.type"));
166 } else {
167 mShowType = new Bool(false);
168 string lLongDescrip("Flag whether message type is outputed in the logs.");
169 Register::Description lDescription(
170 "Show message type in logs",
171 "Bool",
172 "0",
173 lLongDescrip
174 );
175 ioSystem.getRegister().addEntry("lg.show.type", mShowType, lDescription);
176 }
177
178 if(ioSystem.getRegister().isRegistered("lg.show.class")) {
179 mShowClass = castHandleT<Bool>(ioSystem.getRegister().getEntry("lg.show.class"));
180 } else {
181 mShowClass = new Bool(false);
182 string lLongDescrip("Flag whether class name is outputed in the logs.");
183 Register::Description lDescription(
184 "Show class name in logs",
185 "Bool",
186 "0",
187 lLongDescrip
188 );
189 ioSystem.getRegister().addEntry("lg.show.class", mShowClass, lDescription);
190 }
191 Beagle_StackTraceEndM("void LoggerXML::initialize(System& ioSystem)");
192 }
193
194
195 /*!
196 * \brief Write message to the output device.
197 * \param inLevel Log level of the message
198 * \param inType Type of the message to log.
199 * \param inClass Class associated to the message.
200 * \param inMessage Message to log in the output device.
201 */
outputMessage(unsigned int inLevel,Beagle::string inType,Beagle::string inClass,Beagle::string inMessage)202 void LoggerXML::outputMessage(unsigned int inLevel,
203 Beagle::string inType,
204 Beagle::string inClass,
205 Beagle::string inMessage)
206 {
207 Beagle_StackTraceBeginM();
208 if(mTerminated)
209 throw Beagle_RunTimeExceptionM("Can't log in a terminated XML logger!");
210
211 // Log file output
212 if(mLogFileLevel->getWrappedValue()>=inLevel) {
213 if(mActualFileName != mLogFileName->getWrappedValue()) {
214 mActualFileName = mLogFileName->getWrappedValue();
215 if(mStreamerFile != NULL) {
216 mStreamerFile->closeTag();
217 mStreamerFile->closeTag();
218 *mLogOutStream << std::endl;
219 delete mStreamerFile;
220 mStreamerFile = NULL;
221 }
222 if(mLogOutStream) {
223 mLogOutStream->close();
224 delete mLogOutStream;
225 mLogOutStream = NULL;
226 }
227 if(mLogFileName->getWrappedValue().empty() == false) {
228 string lFilenameBak = mLogFileName->getWrappedValue() + "~";
229 std::remove(lFilenameBak.c_str());
230 std::rename(mLogFileName->getWrappedValue().c_str(), lFilenameBak.c_str());
231 mLogOutStream = new std::ofstream(mLogFileName->getWrappedValue().c_str());
232 mStreamerFile = new PACC::XML::Streamer(*mLogOutStream);
233 mStreamerFile->insertHeader();
234 mStreamerFile->openTag("Beagle");
235 mStreamerFile->insertAttribute("version", BEAGLE_VERSION);
236 mStreamerFile->openTag("Logger");
237 }
238 }
239 if(mStreamerFile != NULL) {
240 mStreamerFile->openTag("Log", false);
241 if(mShowLevel->getWrappedValue()) mStreamerFile->insertAttribute("level", uint2str(inLevel));
242 if(mShowType->getWrappedValue()) mStreamerFile->insertAttribute("type", inType);
243 if(mShowClass->getWrappedValue()) mStreamerFile->insertAttribute("class", inClass);
244 mStreamerFile->insertStringContent(inMessage.c_str());
245 mStreamerFile->closeTag();
246 }
247 }
248
249 // Log console output
250 if(mLogConsoleLevel->getWrappedValue()>=inLevel) {
251 if(mStreamerConsole == NULL) {
252 mStreamerConsole = new PACC::XML::Streamer(std::cout);
253 mStreamerConsole->insertHeader();
254 mStreamerConsole->openTag("Beagle");
255 mStreamerConsole->insertAttribute("version", BEAGLE_VERSION);
256 mStreamerConsole->openTag("Logger");
257 }
258 mStreamerConsole->openTag("Log", false);
259 if(mShowLevel->getWrappedValue()) mStreamerConsole->insertAttribute("level", uint2str(inLevel));
260 if(mShowType->getWrappedValue()) mStreamerConsole->insertAttribute("type", inType);
261 if(mShowClass->getWrappedValue()) mStreamerConsole->insertAttribute("class", inClass);
262 mStreamerConsole->insertStringContent(inMessage.c_str());
263 mStreamerConsole->closeTag();
264 }
265 Beagle_StackTraceEndM("void LoggerXML::outputMessage(unsigned int inLevel, string inType, string inClass, string inMessage)");
266 }
267
268
269 /*!
270 * \brief Write Beagle object to the output device.
271 * \param inLevel Log level of the message
272 * \param inType Type of the message to log.
273 * \param inClass Class associated to the message.
274 * \param inObject Beagle object to log in the output device.
275 */
outputObject(unsigned int inLevel,Beagle::string inType,Beagle::string inClass,const Object & inObject)276 void LoggerXML::outputObject(unsigned int inLevel,
277 Beagle::string inType,
278 Beagle::string inClass,
279 const Object& inObject)
280 {
281 Beagle_StackTraceBeginM();
282 if(mTerminated)
283 throw Beagle_RunTimeExceptionM("Can't log in a terminated XML logger!");
284
285 // Log file output
286 if(mLogFileLevel->getWrappedValue()>=inLevel) {
287 if(mActualFileName != mLogFileName->getWrappedValue()) {
288 mActualFileName = mLogFileName->getWrappedValue();
289 if(mStreamerFile != NULL) {
290 mStreamerFile->closeTag();
291 mStreamerFile->closeTag();
292 *mLogOutStream << std::endl;
293 delete mStreamerFile;
294 mStreamerFile = NULL;
295 }
296 if(mLogOutStream) {
297 mLogOutStream->close();
298 delete mLogOutStream;
299 mLogOutStream = NULL;
300 }
301 if(mLogFileName->getWrappedValue().empty() == false) {
302 string lFilenameBak = mLogFileName->getWrappedValue() + "~";
303 std::remove(lFilenameBak.c_str());
304 std::rename(mLogFileName->getWrappedValue().c_str(), lFilenameBak.c_str());
305 mLogOutStream = new std::ofstream(mLogFileName->getWrappedValue().c_str());
306 mStreamerFile = new PACC::XML::Streamer(*mLogOutStream);
307 mStreamerFile->insertHeader();
308 mStreamerFile->openTag("Beagle");
309 mStreamerFile->insertAttribute("version", BEAGLE_VERSION);
310 mStreamerFile->openTag("Logger");
311 }
312 }
313 if(mStreamerFile != NULL) {
314 mStreamerFile->openTag("Log");
315 if(mShowLevel->getWrappedValue()) mStreamerFile->insertAttribute("level", uint2str(inLevel));
316 if(mShowType->getWrappedValue()) mStreamerFile->insertAttribute("type", inType);
317 if(mShowClass->getWrappedValue()) mStreamerFile->insertAttribute("class", inClass);
318 inObject.write(*mStreamerFile);
319 mStreamerFile->closeTag();
320 }
321 }
322
323 // Log console output
324 if(mLogConsoleLevel->getWrappedValue()>=inLevel) {
325 if(mStreamerConsole == NULL) {
326 mStreamerConsole = new PACC::XML::Streamer(std::cout);
327 mStreamerConsole->insertHeader();
328 mStreamerConsole->openTag("Beagle");
329 mStreamerConsole->insertAttribute("version", BEAGLE_VERSION);
330 mStreamerConsole->openTag("Logger");
331 }
332 mStreamerConsole->openTag("Log");
333 if(mShowLevel->getWrappedValue()) mStreamerConsole->insertAttribute("level", uint2str(inLevel));
334 if(mShowType->getWrappedValue()) mStreamerConsole->insertAttribute("type", inType);
335 if(mShowClass->getWrappedValue()) mStreamerConsole->insertAttribute("class", inClass);
336 inObject.write(*mStreamerConsole);
337 mStreamerConsole->closeTag();
338 }
339 Beagle_StackTraceEndM("void LoggerXML::outputObject(unsigned int inLevel, string inType, string inClass, const Object& inObject)");
340 }
341
342
343 /*!
344 * \brief Post-initialize logger.
345 */
postInit(System & ioSystem)346 void LoggerXML::postInit(System& ioSystem)
347 {
348 Beagle_StackTraceBeginM();
349 Logger::postInit(ioSystem);
350
351 mInitialized = true;
352
353 Beagle_LogBasicM(
354 (*this),
355 "logger", "Beagle::LoggerXML",
356 string("Open BEAGLE, version ")+BEAGLE_VERSION
357 );
358
359 switch(mLogConsoleLevel->getWrappedValue()) {
360 case eNothing:
361 {
362 Beagle_LogBasicM(
363 (*this),
364 "logger", "Beagle::LoggerXML",
365 "Console logger initialized, using log level 0 (no message)"
366 );
367 break;
368 }
369 case eBasic:
370 {
371 Beagle_LogBasicM(
372 (*this),
373 "logger", "Beagle::LoggerXML",
374 "Console logger initialized, using log level 1 (essential informations)"
375 );
376 break;
377 }
378 case eStats:
379 {
380 Beagle_LogBasicM(
381 (*this),
382 "logger", "Beagle::LoggerXML",
383 "Console logger initialized, using log level 2 (evolution statistics)"
384 );
385 break;
386 }
387 case eInfo:
388 {
389 Beagle_LogBasicM(
390 (*this),
391 "logger", "Beagle::LoggerXML",
392 "Console logger initialized, using log level 3 (general informations)"
393 );
394 break;
395 }
396 case eDetailed:
397 {
398 Beagle_LogBasicM(
399 (*this),
400 "logger", "Beagle::LoggerXML",
401 "Console logger initialized, using log level 4 (details on operations)"
402 );
403 break;
404 }
405 case eTrace:
406 {
407 Beagle_LogBasicM(
408 (*this),
409 "logger", "Beagle::LoggerXML",
410 "Console logger initialized, using log level 5 (trace of the algorithms)"
411 );
412 break;
413 }
414 case eVerbose:
415 {
416 Beagle_LogBasicM(
417 (*this),
418 "logger", "Beagle::LoggerXML",
419 "Console logger initialized, using log level 6 (details on everything)"
420 );
421 #ifdef BEAGLE_NDEBUG
422 Beagle_LogBasicM(
423 (*this),
424 "logger", "Beagle::LoggerXML",
425 "Console log level 6 (verbose) is unused as optimization mode is enabled"
426 );
427 #endif // BEAGLE_NDEBUG
428 break;
429 }
430 case eDebug:
431 {
432 Beagle_LogBasicM(
433 (*this),
434 "logger", "Beagle::LoggerXML",
435 "Console logger initialized, using log level 7 (debug)"
436 );
437 #ifdef BEAGLE_NDEBUG
438 Beagle_LogBasicM(
439 (*this),
440 "logger", "Beagle::LoggerXML",
441 "Console log level 7 (debug) is unused as optimization mode is enabled"
442 );
443 #endif // BEAGLE_NDEBUG
444 #ifndef BEAGLE_FULL_DEBUG
445 Beagle_LogBasicM(
446 (*this),
447 "logger", "Beagle::LoggerXML",
448 "Console log level 7 (debug) is unused as full debug mode is disabled"
449 );
450 #endif // BEAGLE_FULL_DEBUG
451 break;
452 }
453 default:
454 {
455 Beagle_LogBasicM(
456 (*this),
457 "logger", "Beagle::LoggerXML",
458 string("Console logger initialized, using log level ")+
459 uint2str(mLogConsoleLevel->getWrappedValue())+
460 " (unused)"
461 );
462 break;
463 }
464 }
465
466 if(mLogFileName->getWrappedValue().empty()) {
467 Beagle_LogBasicM(
468 (*this),
469 "logger", "Beagle::LoggerXML",
470 "File logging disabled"
471 );
472 }
473 else {
474 switch(mLogFileLevel->getWrappedValue()) {
475 case eNothing:
476 {
477 Beagle_LogBasicM(
478 (*this),
479 "logger", "Beagle::LoggerXML",
480 "File logger initialized, using log level 0 (no message)"
481 );
482 break;
483 }
484 case eBasic:
485 {
486 Beagle_LogBasicM(
487 (*this),
488 "logger", "Beagle::LoggerXML",
489 "File logger initialized, using log level 1 (essential informations)"
490 );
491 break;
492 }
493 case eStats:
494 {
495 Beagle_LogBasicM(
496 (*this),
497 "logger", "Beagle::LoggerXML",
498 "File logger initialized, using log level 2 (evolution statistics)"
499 );
500 break;
501 }
502 case eInfo:
503 {
504 Beagle_LogBasicM(
505 (*this),
506 "logger", "Beagle::LoggerXML",
507 "File logger initialized, using log level 3 (general informations)"
508 );
509 break;
510 }
511 case eDetailed:
512 {
513 Beagle_LogBasicM(
514 (*this),
515 "logger", "Beagle::LoggerXML",
516 "File logger initialized, using log level 4 (details on operations)"
517 );
518 break;
519 }
520 case eTrace:
521 {
522 Beagle_LogBasicM(
523 (*this),
524 "logger", "Beagle::LoggerXML",
525 "File logger initialized, using log level 5 (trace of the algorithms)"
526 );
527 break;
528 }
529 case eVerbose:
530 {
531 Beagle_LogBasicM(
532 (*this),
533 "logger", "Beagle::LoggerXML",
534 "File logger initialized, using log level 6 (details on everything)"
535 );
536 #ifdef BEAGLE_NDEBUG
537 Beagle_LogBasicM(
538 (*this),
539 "logger", "Beagle::LoggerXML",
540 "File log level 6 (verbose) is unused as optimization mode is enabled"
541 );
542 #endif // BEAGLE_NDEBUG
543 break;
544 }
545 case eDebug:
546 {
547 Beagle_LogBasicM(
548 (*this),
549 "logger", "Beagle::LoggerXML",
550 "File logger initialized, using log level 7 (debug)"
551 );
552 #ifdef BEAGLE_NDEBUG
553 Beagle_LogBasicM(
554 (*this),
555 "logger", "Beagle::LoggerXML",
556 "File log level 7 (debug) is unused as optimization mode is enabled"
557 );
558 #endif // BEAGLE_NDEBUG
559 #ifndef BEAGLE_FULL_DEBUG
560 Beagle_LogBasicM(
561 (*this),
562 "logger", "Beagle::LoggerXML",
563 "File log level 7 (debug) is unused as full debug mode is disabled"
564 );
565 #endif // BEAGLE_FULL_DEBUG
566 break;
567 }
568 default:
569 {
570 Beagle_LogBasicM(
571 (*this),
572 "logger", "Beagle::LoggerXML",
573 string("File logger initialized, using log level ")+
574 uint2str(mLogFileLevel->getWrappedValue())+
575 " (unused)"
576 );
577 break;
578 }
579 }
580
581 Beagle_LogBasicM(
582 (*this),
583 "logger", "Beagle::LoggerXML",
584 string("Logging to file named \"")+mLogFileName->getWrappedValue()+string("\"")
585 );
586 }
587
588 for(std::list< Message,BEAGLE_STLALLOCATOR<Message> >::const_iterator lIter = mBuffer.begin();
589 lIter != mBuffer.end(); ++lIter) {
590 outputMessage(lIter->mLogLevel, lIter->mType, lIter->mClass, lIter->mMessage);
591 }
592 mBuffer.clear();
593 Beagle_StackTraceEndM("void LoggerXML::postInit(System& ioSystem)");
594 }
595
596
597
598 /*!
599 * \brief Terminate XML logger operations.
600 */
terminate()601 void LoggerXML::terminate()
602 {
603 Beagle_StackTraceBeginM();
604 if(mTerminated == false) {
605 mTerminated = true;
606 if(mStreamerFile != NULL) {
607 mStreamerFile->closeTag();
608 mStreamerFile->closeTag();
609 *mLogOutStream << std::endl;
610 delete mStreamerFile;
611 mStreamerFile = NULL;
612 }
613 if(mStreamerConsole != NULL) {
614 mStreamerConsole->closeTag();
615 mStreamerConsole->closeTag();
616 std::cout << std::endl;
617 delete mStreamerConsole;
618 mStreamerConsole = NULL;
619 }
620 if(mLogOutStream) {
621 mLogOutStream->close();
622 delete mLogOutStream;
623 mLogOutStream = NULL;
624 }
625 }
626 Beagle_StackTraceEndM("void LoggerXML::terminate()");
627 }
628
629