00001 /* 00002 Copyright 2007, 2008, 2009, 2010, 2011 Instituto de Sistemas e Robotica, Instituto Superior Tecnico 00003 00004 This file is part of MeRMaID. 00005 00006 MeRMaID is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU Lesser General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 MeRMaID is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public License 00017 along with MeRMaID. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 00021 00022 /** 00023 * @Filename Logger.hpp 00024 * @Description Logger declaration 00025 * @Status Finished 00026 * @Version $Id: Logger.hpp 1 2011-03-04 18:13:18Z jreis $ 00027 * @Maintainer Joao Reis (joaocgreis@gmail.com) 00028 */ 00029 00030 #ifndef LOGGER_HPP 00031 #define LOGGER_HPP 00032 00033 00034 00035 /** 00036 * Enables a prototype for quick profiling of code, based on the logger. 00037 * This was just an experiment, but it's already done so I'll let it be. 00038 */ 00039 #undef MERMAID_LOGGER_QUICK_PROFILING 00040 00041 // Compile time Logger configurations 00042 /** 00043 * Disables the shortcuts to the reporting levels, for speed purposes. 00044 * Please mind that this will not affect any of the methods called log. 00045 */ 00046 #undef MERMAID_LOGGER_DISABLE_REPORTING 00047 // If we really need it, we could create another class, DummyLogger, 00048 // that completely implemented the logger with empty methods. 00049 // Then we would only need to change the lines where the logger is crated. 00050 00051 00052 00053 #include <ctime> 00054 #include <fstream> 00055 #include <list> 00056 #include <map> 00057 #include <set> 00058 #include <sstream> 00059 #include <stack> 00060 #include <string> 00061 00062 #ifdef MERMAID_LOGGER_QUICK_PROFILING 00063 #include <sys/time.h> 00064 #include <time.h> 00065 #endif //MERMAID_LOGGER_QUICK_PROFILING 00066 00067 #include "ace/Synch.h" 00068 00069 #include <boost/foreach.hpp> 00070 #define foreach BOOST_FOREACH 00071 00072 00073 #include <DataBox.hpp> 00074 00075 00076 00077 /** 00078 * Logs an ERROR using a <code>std::ostringstream</code>. 00079 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00080 * <code>message</code> into it and calls the method <code>error</code> 00081 * from the logger you specified. 00082 * @see mermaid::support::logging::Logger.error() 00083 * @param logger The logger to use. Must evaluate to an instance of 00084 * <code>mermaid::support::logging::Logger</code> 00085 * @param message Somethog to be inserted into the 00086 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00087 */ 00088 #define LERROR(logger, message) {std::ostringstream tmp; tmp << message; (logger)->error(tmp.str());} 00089 /** 00090 * Logs a WARN using a <code>std::ostringstream</code>. 00091 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00092 * <code>message</code> into it and calls the method <code>warn</code> 00093 * from the logger you specified. 00094 * @see mermaid::support::logging::Logger.warn() 00095 * @param logger The logger to use. Must evaluate to an instance of 00096 * <code>mermaid::support::logging::Logger</code> 00097 * @param message Somethog to be inserted into the 00098 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00099 */ 00100 #define LWARN(logger, message) {std::ostringstream tmp; tmp << message; (logger)->warn(tmp.str());} 00101 /** 00102 * Logs an INFO using a <code>std::ostringstream</code>. 00103 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00104 * <code>message</code> into it and calls the method <code>info</code> 00105 * from the logger you specified. 00106 * @see mermaid::support::logging::Logger.info() 00107 * @param logger The logger to use. Must evaluate to an instance of 00108 * <code>mermaid::support::logging::Logger</code> 00109 * @param message Somethog to be inserted into the 00110 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00111 */ 00112 #define LINFO(logger, message) {std::ostringstream tmp; tmp << message; (logger)->info(tmp.str());} 00113 00114 #ifndef MERMAID_LOGGER_DISABLE_REPORTING 00115 /** 00116 * Logs a BEGIN using a <code>std::ostringstream</code>. 00117 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00118 * <code>message</code> into it and calls the method <code>begin</code> 00119 * from the logger you specified. 00120 * @see mermaid::support::logging::Logger.begin() 00121 * @param logger The logger to use. Must evaluate to an instance of 00122 * <code>mermaid::support::logging::Logger</code> 00123 * @param message Somethog to be inserted into the 00124 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00125 */ 00126 #define LBEGIN(logger, message) {std::ostringstream tmp; tmp << message; (logger)->begin(tmp.str());} 00127 /** 00128 * Logs a SEPARATOR using a <code>std::ostringstream</code>. 00129 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00130 * <code>message</code> into it and calls the method <code>separator</code> 00131 * from the logger you specified. 00132 * @see mermaid::support::logging::Logger.separator() 00133 * @param logger The logger to use. Must evaluate to an instance of 00134 * <code>mermaid::support::logging::Logger</code> 00135 * @param message Somethog to be inserted into the 00136 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00137 */ 00138 #define LSEPARATOR(logger, message) {std::ostringstream tmp; tmp << message; (logger)->separator(tmp.str());} 00139 /** 00140 * Logs a STEP using a <code>std::ostringstream</code>. 00141 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00142 * <code>message</code> into it and calls the method <code>step</code> 00143 * from the logger you specified. 00144 * @see mermaid::support::logging::Logger.step() 00145 * @param logger The logger to use. Must evaluate to an instance of 00146 * <code>mermaid::support::logging::Logger</code> 00147 * @param message Somethog to be inserted into the 00148 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00149 */ 00150 #define LSTEP(logger, message) {std::ostringstream tmp; tmp << message; (logger)->step(tmp.str());} 00151 /** 00152 * Logs an END using a <code>std::ostringstream</code>. 00153 * This macro crates a temporary <code>std::ostringstream</code>, inserts 00154 * <code>message</code> into it and calls the method <code>end</code> 00155 * from the logger you specified. 00156 * @see mermaid::support::logging::Logger.end() 00157 * @param logger The logger to use. Must evaluate to an instance of 00158 * <code>mermaid::support::logging::Logger</code> 00159 * @param message Somethog to be inserted into the 00160 * <code>std::ostringstream</code>. May contain more <code><<</code> operators. 00161 */ 00162 #define LEND(logger, message) {std::ostringstream tmp; tmp << message; (logger)->end(tmp.str());} 00163 #else 00164 /** Disabled by MERMAID_LOGGER_DISABLE_REPORTING in compile time */ 00165 #define LBEGIN(logger, message) {} 00166 /** Disabled by MERMAID_LOGGER_DISABLE_REPORTING in compile time */ 00167 #define LSEPARATOR(logger, message) {} 00168 /** Disabled by MERMAID_LOGGER_DISABLE_REPORTING in compile time */ 00169 #define LSTEP(logger, message) {} 00170 /** Disabled by MERMAID_LOGGER_DISABLE_REPORTING in compile time */ 00171 #define LEND(logger, message) {} 00172 #endif // MERMAID_LOGGER_DISABLE_REPORTING 00173 00174 00175 00176 namespace mermaid 00177 { 00178 namespace support 00179 { 00180 /// Namespace for the Logging Framework. 00181 namespace logging 00182 { 00183 using boost::shared_ptr; 00184 00185 /** 00186 * @enum LogLevel 00187 * @Description The LogLevel enum lists all the logger levels. 00188 * @Author Joao Reis 00189 */ 00190 enum LogLevel { 00191 // Error levels 00192 LOG_ERROR, /**< Error level (Error levels group) */ 00193 LOG_WARN, /**< Warn level (Error levels group) */ 00194 LOG_INFO, /**< Info level (Error levels group) */ 00195 // Reporting levels 00196 LOG_BEGIN, /**< Begin level (Reporting levels group) */ 00197 LOG_STEP, /**< Step level (Reporting levels group) */ 00198 LOG_SEPARATOR, /**< Separator level (Reporting levels group) */ 00199 LOG_END /**< End level (Reporting levels group) */ 00200 }; 00201 00202 00203 00204 /** 00205 * @Class LogMessage 00206 * @Description This class represents a message of the logger. 00207 * 00208 * The LogMessage is sent by the Logger class to the LogOutput(s). 00209 * @Author Joao Reis 00210 */ 00211 class LogMessage 00212 { 00213 public: 00214 /** 00215 * @Description Creates a new LogMessage. 00216 * @Argument logLevel The level of the message. 00217 * @Argument time The time when the message was issued. 00218 * @Argument indentation Indentation level of the message for 00219 * reporting levels. 00220 * @Argument prefix The logger prefix when the message was issued. 00221 * @Argument message The message to log. 00222 * @Author Joao Reis 00223 */ 00224 LogMessage (const LogLevel& logLevel, 00225 const time_t& time, 00226 const int& indentation, 00227 const std::string& prefix, 00228 const std::string& message) : 00229 logLevel_ (logLevel), 00230 time_ (time), 00231 indentation_ (indentation), 00232 prefix_ (prefix), 00233 message_ (message) { 00234 } 00235 /** 00236 * @Description Gets the LogLevel of the message. 00237 * @Returns The LogLevel of the message. 00238 * @Author Joao Reis 00239 */ 00240 inline const LogLevel& getLogLevel() const { 00241 return logLevel_; 00242 } 00243 /** 00244 * @Description Gets the time when the message was issued. 00245 * @Returns The time when the message was issued. 00246 * @Author Joao Reis 00247 */ 00248 inline const time_t& getTime() const { 00249 return time_; 00250 } 00251 /** 00252 * @Description Gets the indentation of the message. 00253 * @Returns The indentation of the message. 00254 * @Author Joao Reis 00255 */ 00256 inline const int& getIndentation() const { 00257 return indentation_; 00258 } 00259 /** 00260 * @Description Gets the prefix of the logger when the message was issued. 00261 * @Returns The prefix of the logger. 00262 * @Author Joao Reis 00263 */ 00264 inline const std::string& getPrefix() const { 00265 return prefix_; 00266 } 00267 /** 00268 * @Description Gets the message. 00269 * @Returns The actual message. 00270 * @Author Joao Reis 00271 */ 00272 inline const std::string& getMessage() const { 00273 return message_; 00274 } 00275 00276 private: 00277 LogLevel logLevel_; 00278 time_t time_; 00279 int indentation_; 00280 std::string prefix_; 00281 std::string message_; 00282 }; 00283 00284 00285 00286 /** 00287 * @Class LogOutput 00288 * @Description LogOutput is something that handles the Logger output. 00289 * 00290 * LogOutput is an abstract class, where all the LogMessage's 00291 * generated by the Logger go. 00292 * @Author Joao Reis 00293 */ 00294 class LogOutput 00295 { 00296 public: 00297 /** 00298 * @Description Logs a message generated by the logger. 00299 * @Argument logMessage the message to log. 00300 * @Author Joao Reis 00301 */ 00302 virtual void outputMessage (const LogMessage& logMessage) = 0; 00303 virtual ~LogOutput() {} 00304 }; 00305 00306 00307 00308 /** 00309 * @Class Logger 00310 * @Description Main class of the logger framework. 00311 * @Author Joao Reis 00312 */ 00313 class Logger 00314 { 00315 public: 00316 // Knowledge about the levels should be all contained in the 00317 // LogLevels enum, but the logger also knows about them. 00318 // To minimize the number of classes that know about the 00319 // levels, only methods that don't depend on them are maked 00320 // virtual. Shortcuts should stay in this base class. 00321 00322 /** 00323 * @Description Sets the prefix of the Logger. 00324 * 00325 * Each Logger can have exactly one prefix that is printed 00326 * before every message. 00327 * @Argument prefix The prefix to use. 00328 * @Author Joao Reis 00329 */ 00330 virtual void setPrefix (const std::string& prefix) = 0; 00331 00332 00333 00334 /** 00335 * @Description Enables a specific output for a specific log level. 00336 * @Argument logLevel The logLevel to associate. 00337 * @Argument logOutput The logOutput to associate with the logLevel. 00338 * @Author Joao Reis 00339 */ 00340 virtual void enableLogLevel (const LogLevel& logLevel, 00341 shared_ptr<LogOutput> logOutput) = 0; 00342 /** 00343 * @Description Enables the error levels (LOG_ERROR, LOG_WARN and LOG_INFO) for the given output. 00344 * @Argument logOutput Will enable the levels for this logOutput. 00345 * @Author Joao Reis 00346 */ 00347 void enableErrorLogLevels (shared_ptr<LogOutput> logOutput); 00348 /** 00349 * @Description Enables the reporting levels (LOG_BEGIN, LOG_END, LOG_STEP and LOG_SEPARATOR) for the given output. 00350 * @Argument logOutput Will enable the levels for this logOutput. 00351 * @Author Joao Reis 00352 */ 00353 void enableReportingLogLevels (shared_ptr<LogOutput> logOutput); 00354 /** 00355 * @Description Enables all levels for the given output. 00356 * @Argument logOutput Will enable the levels for this logOutput. 00357 * @Author Joao Reis 00358 */ 00359 void enableAllLogLevels (shared_ptr<LogOutput> logOutput); 00360 /** 00361 * @Description Disables a specified output for a specific level. 00362 * @Argument logLevel The logOutput will be disabled only for this level. 00363 * @Argument logOutput The logOutput to disble for the logLevel. 00364 * @Author Joao Reis 00365 */ 00366 virtual void disableLogLevel (const LogLevel& logLevel, 00367 shared_ptr<LogOutput> logOutput) = 0; 00368 /** 00369 * @Description Disables all outputs for the specified logLevel. 00370 * @Argument logLevel All the outputs of this level will be disabled. 00371 * @Author Joao Reis 00372 */ 00373 virtual void disableLogLevel (const LogLevel& logLevel) = 0; 00374 /** 00375 * @Description Disables all levels for the given output. 00376 * @Argument logOutput Will disable the levels for this logOutput. 00377 * @Author Joao Reis 00378 */ 00379 void disableAllLogLevels (shared_ptr<LogOutput> logOutput); 00380 /** 00381 * @Description Disables all outputs for all the levels, completely stopping the Logger. 00382 * 00383 * This method will stop the logger if you need it. It is 00384 * necessary because you cannot delete the logger, it is always a shared_ptr. 00385 * @Author Joao Reis 00386 */ 00387 void disableAllLogLevels(); 00388 00389 00390 00391 /** 00392 * @Description Logs a message, given in the form of a string. 00393 * 00394 * This is the main method of the logger, all the others 00395 * just call this one internally. 00396 * 00397 * Please mind that this method is not affected by MERMAID_LOGGER_DISABLE_REPORTING. 00398 * @Argument logLevel The log level to use. 00399 * @Argument message The message to log. 00400 * @Author Joao Reis 00401 */ 00402 virtual void log (const LogLevel& logLevel, 00403 const std::string& message) = 0; 00404 /** 00405 * @Description Logs a DataBox. 00406 * 00407 * Please mind that this method is not affected by MERMAID_LOGGER_DISABLE_REPORTING. 00408 * @Argument logLevel The log level to use. 00409 * @Argument message The message to log. 00410 * @Author Joao Reis 00411 */ 00412 void log (const LogLevel& logLevel, 00413 const mermaid::support::data::DataBox& message); 00414 00415 00416 00417 /** 00418 * @Description Logs a string with the level LOG_ERROR. 00419 * @Argument message The message to log. 00420 * @Author Joao Reis 00421 */ 00422 void error (const std::string& message); 00423 /** 00424 * @Description Logs a string with the level LOG_WARN. 00425 * @Argument message The message to log. 00426 * @Author Joao Reis 00427 */ 00428 void warn (const std::string& message); 00429 /** 00430 * @Description Logs a string with the level LOG_INFO. 00431 * @Argument message The message to log. 00432 * @Author Joao Reis 00433 */ 00434 void info (const std::string& message); 00435 /** 00436 * @Description Logs a string with the level LOG_BEGIN. 00437 * @Argument message The message to log. 00438 * @Author Joao Reis 00439 */ 00440 void begin (const std::string& message = ""); 00441 /** 00442 * @Description Logs a string with the level LOG_SEPARATOR. 00443 * @Argument message The message to log. 00444 * @Author Joao Reis 00445 */ 00446 void separator (const std::string& message = ""); 00447 /** 00448 * @Description Logs a string with the level LOG_STEP. 00449 * @Argument message The message to log. 00450 * @Author Joao Reis 00451 */ 00452 void step (const std::string& message); 00453 /** 00454 * @Description Logs a string with the level LOG_END. 00455 * @Argument message The message to log. 00456 * @Author Joao Reis 00457 */ 00458 void end (const std::string& message = ""); 00459 00460 00461 00462 protected: 00463 Logger() {}; 00464 // virtual ~Logger() {}; 00465 // needed by effc++, hated by shared_ptr 00466 }; 00467 00468 00469 00470 /** 00471 * @Class ThreadSafeLogger 00472 * @Description Thread safe implementation of the logger. 00473 * @Author Joao Reis 00474 */ 00475 class ThreadSafeLogger : public Logger 00476 { 00477 public: 00478 /** 00479 * @Description Creates a new ThreadSafeLogger with an empty prefix. 00480 * @Returns A shared_ptr to the new Logger. 00481 * @Author Joao Reis 00482 */ 00483 static shared_ptr<Logger> build(); 00484 /** 00485 * @Description Creates a new ThreadSafeLogger with the given prefix. 00486 * @Returns A shared_ptr to the new Logger. 00487 * @Argument prefix The prefix to use. 00488 * @Author Joao Reis 00489 */ 00490 static shared_ptr<Logger> build (const std::string& prefix); 00491 00492 00493 00494 /** 00495 * @Description Sets the prefix of the ThreadSafeLogger. 00496 * 00497 * Each Logger can have exactly one prefix that is printed 00498 * before every message. 00499 * @Argument prefix The prefix to use. 00500 * @Author Joao Reis 00501 */ 00502 virtual void setPrefix (const std::string& prefix); 00503 00504 00505 00506 /** 00507 * @Description Enables a specific output for a specific log level. 00508 * @Argument logLevel The logLevel to associate. 00509 * @Argument logOutput The logOutput to associate with the logLevel. 00510 * @Author Joao Reis 00511 */ 00512 virtual void enableLogLevel (const LogLevel& logLevel, 00513 shared_ptr<LogOutput> logOutput); 00514 /** 00515 * @Description Disables a specified output for a specific level. 00516 * @Argument logLevel The logOutput will be disabled only for this level. 00517 * @Argument logOutput The logOutput to disble for the logLevel. 00518 * @Author Joao Reis 00519 */ 00520 virtual void disableLogLevel (const LogLevel& logLevel, 00521 shared_ptr<LogOutput> logOutput); 00522 /** 00523 * @Description Disables all outputs for the specified logLevel. 00524 * @Argument logLevel All the outputs of this level will be disabled. 00525 * @Author Joao Reis 00526 */ 00527 virtual void disableLogLevel (const LogLevel& logLevel); 00528 00529 00530 00531 /** 00532 * @Description Logs a message, given in the form of a string. 00533 * 00534 * This is the main method of the logger, all the others 00535 * just call this one internally. 00536 * 00537 * Please mind that this method is not affected by MERMAID_LOGGER_DISABLE_REPORTING. 00538 * @Argument logLevel The log level to use. 00539 * @Argument message The message to log. 00540 * @Author Joao Reis 00541 */ 00542 virtual void log (const LogLevel& logLevel, 00543 const std::string& message); 00544 00545 00546 00547 private: 00548 ThreadSafeLogger(); 00549 ThreadSafeLogger (const std::string& prefix); 00550 00551 ACE_RW_Mutex mutex_; 00552 int indentation_; 00553 std::string prefix_; 00554 std::map <LogLevel, std::list<shared_ptr<LogOutput> > > levelOutputs_; 00555 }; 00556 00557 00558 00559 /** 00560 * @Class FastLogger 00561 * @Description Fast implementation of the logger, without any thread 00562 * synchronization. 00563 * @Author Joao Reis 00564 */ 00565 class FastLogger : public Logger 00566 { 00567 public: 00568 /** 00569 * @Description Creates a new FastLogger with an empty prefix. 00570 * @Returns A shared_ptr to the new Logger. 00571 * @Author Joao Reis 00572 */ 00573 static shared_ptr<Logger> build(); 00574 /** 00575 * @Description Creates a new FastLogger with the given prefix. 00576 * @Returns A shared_ptr to the new Logger. 00577 * @Argument prefix The prefix to use. 00578 * @Author Joao Reis 00579 */ 00580 static shared_ptr<Logger> build (const std::string& prefix); 00581 00582 00583 00584 /** 00585 * @Description Sets the prefix of the FastLogger. 00586 * 00587 * Each Logger can have exactly one prefix that is printed 00588 * before every message. 00589 * @Argument prefix The prefix to use. 00590 * @Author Joao Reis 00591 */ 00592 virtual void setPrefix (const std::string& prefix); 00593 00594 00595 00596 /** 00597 * @Description Enables a specific output for a specific log level. 00598 * @Argument logLevel The logLevel to associate. 00599 * @Argument logOutput The logOutput to associate with the logLevel. 00600 * @Author Joao Reis 00601 */ 00602 virtual void enableLogLevel (const LogLevel& logLevel, 00603 shared_ptr<LogOutput> logOutput); 00604 /** 00605 * @Description Disables a specified output for a specific level. 00606 * @Argument logLevel The logOutput will be disabled only for this level. 00607 * @Argument logOutput The logOutput to disble for the logLevel. 00608 * @Author Joao Reis 00609 */ 00610 virtual void disableLogLevel (const LogLevel& logLevel, 00611 shared_ptr<LogOutput> logOutput); 00612 /** 00613 * @Description Disables all outputs for the specified logLevel. 00614 * @Argument logLevel All the outputs of this level will be disabled. 00615 * @Author Joao Reis 00616 */ 00617 virtual void disableLogLevel (const LogLevel& logLevel); 00618 00619 00620 00621 /** 00622 * @Description Logs a message, given in the form of a string. 00623 * 00624 * This is the main method of the logger, all the others 00625 * just call this one internally. 00626 * 00627 * Please mind that this method is not affected by MERMAID_LOGGER_DISABLE_REPORTING. 00628 * @Argument logLevel The log level to use. 00629 * @Argument message The message to log. 00630 * @Author Joao Reis 00631 */ 00632 virtual void log (const LogLevel& logLevel, 00633 const std::string& message); 00634 00635 00636 00637 private: 00638 FastLogger(); 00639 FastLogger (const std::string& prefix); 00640 00641 int updateIndentation_ (const LogLevel& logLevel); 00642 int indentation_; 00643 std::string prefix_; 00644 std::map <LogLevel, std::list<shared_ptr<LogOutput> > > levelOutputs_; 00645 #ifdef MERMAID_LOGGER_QUICK_PROFILING 00646 std::stack<struct timeval> beginTimes_; 00647 #endif //MERMAID_LOGGER_QUICK_PROFILING 00648 }; 00649 00650 00651 00652 /** 00653 * @Class ThreadSafeOutput 00654 * @Description Adds mutual exclusion to another output. 00655 * @Author Joao Reis 00656 */ 00657 class ThreadSafeOutput : public LogOutput 00658 { 00659 public: 00660 /** 00661 * @Description ThreadSafeOutput 00662 * @Argument output The output to guard. 00663 * @Returns A shared_ptr to the new ThreadSafeOutput. 00664 * @Author Joao Reis 00665 */ 00666 static shared_ptr<ThreadSafeOutput> build (shared_ptr<LogOutput> output); 00667 /** 00668 * @Description Logs a message generated by the logger. 00669 * @Argument logMessage the message to log. 00670 * @Author Joao Reis 00671 */ 00672 void outputMessage (const LogMessage& logMessage); 00673 00674 private: 00675 ThreadSafeOutput (shared_ptr<LogOutput> output); 00676 ACE_Mutex mutex_; 00677 shared_ptr<LogOutput> output_; 00678 }; 00679 00680 00681 00682 /** 00683 * @Class TerminalOutput 00684 * @Description Prints LogMessage's to the standard output. 00685 * @Author Joao Reis 00686 */ 00687 class TerminalOutput : public LogOutput 00688 { 00689 public: 00690 /** 00691 * @Description Gets the TerminalOutput. 00692 * Beware that the TerminalOutput is a singleton accessible only 00693 * through a ThreadSafeOutput. 00694 * @Returns A shared_ptr to the new TerminalOutput. 00695 * @Author Joao Reis 00696 */ 00697 static shared_ptr<ThreadSafeOutput> build(); 00698 /** 00699 * @Description Logs a message generated by the logger. 00700 * @Argument logMessage the message to log. 00701 * @Author Joao Reis 00702 */ 00703 void outputMessage (const LogMessage& logMessage); 00704 00705 private: 00706 TerminalOutput() {} 00707 static shared_ptr<ThreadSafeOutput> instance_; 00708 }; 00709 00710 00711 00712 /** 00713 * @Class FileOutput 00714 * @Description Appends LogMessage's to a file. 00715 * @Author Joao Reis 00716 */ 00717 class FileOutput : public LogOutput 00718 { 00719 public: 00720 /** 00721 * @Description Creates a new FileOutput for the given file. 00722 * Beware that only one file output should exist for each file. 00723 * You are responsible to sychronize that output with a 00724 * ThreadSafeOutput if you need. 00725 * @Returns A shared_ptr to the new FileOutput. 00726 * @Argument fileName The name of the file to append to. 00727 * @Author Joao Reis 00728 */ 00729 static shared_ptr<FileOutput> build (std::string fileName); 00730 /** 00731 * @Description Logs a message generated by the logger. 00732 * @Argument logMessage the message to log. 00733 * @Author Joao Reis 00734 */ 00735 void outputMessage (const LogMessage& logMessage); 00736 00737 private: 00738 FileOutput (std::string fileName); 00739 std::string fileName_; 00740 std::ofstream fileStream_; 00741 }; 00742 00743 00744 00745 /** 00746 * @Class LogScope 00747 * @Description LogScope is a helper to use the logger. 00748 * 00749 * LogScope automatically makes the end level calls 00750 * within it's destructor. 00751 * @Author Joao Reis 00752 */ 00753 class LogScope 00754 { 00755 public: 00756 /** 00757 * @Description Constructor: No begin message and empty end message. 00758 * This is only used to call begin and call end automatically 00759 * when the object goes out of scope. 00760 * @Argument logger The logger to use. 00761 * @Author Joao Reis 00762 */ 00763 LogScope (shared_ptr<Logger> logger); 00764 /** 00765 * @Description Constructor: Only a begin message. 00766 * @Argument logger The logger to use. 00767 * @Argument beginMessage The message to log with level LOG_BEGIN right away. 00768 * @Author Joao Reis 00769 */ 00770 LogScope (shared_ptr<Logger> logger, 00771 const std::string& beginMessage); 00772 /** 00773 * @Description Constructor: Begin and end messages. 00774 * @Argument logger The logger to use. 00775 * @Argument beginMessage The message to log with level LOG_BEGIN right away. 00776 * @Argument endMessage The message to log with level LOG_END when the class is destroyed. 00777 * @Author Joao Reis 00778 */ 00779 LogScope (shared_ptr<Logger> logger, 00780 const std::string& beginMessage, 00781 const std::string& endMessage); 00782 ~LogScope(); 00783 private: 00784 shared_ptr<Logger> logger_; 00785 std::string endMessage_; 00786 bool shouldShowMessage_; 00787 00788 LogScope (LogScope &logScope); 00789 }; 00790 00791 00792 00793 namespace LogAux 00794 { 00795 using std::set; 00796 using std::string; 00797 using std::ostringstream; 00798 00799 inline string toStr (const set<string>& strings) 00800 { 00801 ostringstream s; 00802 s << "["; 00803 bool isFirst = true; 00804 foreach (string t, strings) { 00805 if (!isFirst) 00806 s << ","; 00807 s << " " << t; 00808 isFirst = false; 00809 } 00810 s << " ]"; 00811 return s.str(); 00812 } 00813 } 00814 00815 00816 00817 // Logger inline methods 00818 00819 inline void Logger::log (const LogLevel& logLevel, 00820 const mermaid::support::data::DataBox& message) 00821 { 00822 log (logLevel, static_cast<std::string> (message)); 00823 } 00824 00825 00826 00827 inline void Logger::error (const std::string& message) 00828 { 00829 log (LOG_ERROR, message); 00830 } 00831 inline void Logger::warn (const std::string& message) 00832 { 00833 log (LOG_WARN, message); 00834 } 00835 inline void Logger::info (const std::string& message) 00836 { 00837 log (LOG_INFO, message); 00838 } 00839 #ifndef MERMAID_LOGGER_DISABLE_REPORTING 00840 inline void Logger::begin (const std::string& message) 00841 { 00842 log (LOG_BEGIN, message); 00843 } 00844 inline void Logger::separator (const std::string& message) 00845 { 00846 log (LOG_SEPARATOR, message); 00847 } 00848 inline void Logger::step (const std::string& message) 00849 { 00850 log (LOG_STEP, message); 00851 } 00852 inline void Logger::end (const std::string& message) 00853 { 00854 log (LOG_END, message); 00855 } 00856 #else 00857 inline void Logger::begin (const std::string& message) {} 00858 inline void Logger::separator (const std::string& message) {} 00859 inline void Logger::step (const std::string& message) {} 00860 inline void Logger::end (const std::string& message) {} 00861 #endif // MERMAID_LOGGER_DISABLE_REPORTING 00862 } 00863 } 00864 } 00865 00866 #endif // LOGGER_HPP