/* * File: Logging.h * * Copyright (c) Freescale Semiconductor, Inc. All rights reserved. * See included license file for license details. */ #if !defined(_Logging_h_) #define _Logging_h_ #include #include #include /*! * \brief Base logger class. * * There are two types of logging levels that are used by this class. First * there is the filter level. Any log message that is assigned a level * higher than the current filter level is discarded. Secondly there is the * current output level. Log messages that do not have their own level * use the current output level to determine if they should be shown or * not. * * The two methods setFilterLevel() and setOutputLevel() set the filter * and default output logging levels, respectively. There are corresponding * getter methods as well. Both the filter and output levels are * initialized to #INFO during object construction. * * Most use of the logger classes is expected to be through the Log * class. It provides static logging methods that call through to a global * singleton logger instance. There is also a Log::SetOutputLevel utility * class that makes it extremely easiy to temporarily change the default * output logging level. * * Of all the overloaded log() methods in this class, none of them are * really expected to be reimplemented by subclasses. Instead, there is * the single protected _log() method that takes a simple string pointer. * The other log methods all wind up calling _log(), so it provides a * single point to override. In fact, _log() is pure virtual, so subclasses * must implement it. * * \see Log */ class Logger { public: //! \brief Logging levels. enum log_level_t { URGENT = 0, //!< The lowest level, for messages that must always be logged. ERROR, //!< For fatal error messages. WARNING, //!< For non-fatal warning messages. INFO, //!< The normal log level, for status messages. INFO2, //!< For verbose status messages. DEBUG, //!< For internal reporting. DEBUG2 //!< Highest log level; verbose debug logging. }; public: //! \brief Default constructor. Logger() : m_filter(INFO), m_level(INFO) {} //! \brief Destructor. virtual ~Logger() {} //! \name Logging levels //@{ //! \brief Changes the logging level to \a level. inline void setFilterLevel(log_level_t level) { m_filter = level; } //! \brief Returns the current logging filter level. inline log_level_t getFilterLevel() const { return m_filter; } //! \brief Changes the logging output level to \a level. inline void setOutputLevel(log_level_t level) { m_level = level; } //! \brief Returns the current logging output level. inline log_level_t getOutputLevel() const { return m_level; } //@} //! \name Logging //@{ //! \brief Log with format. virtual void log(const char * fmt, ...); //! \brief Log a string object. virtual void log(const std::string & msg) { log(msg.c_str()); } //! \brief Log with format at a specific output level. virtual void log(log_level_t level, const char * fmt, ...); //! \brief Log a string output at a specific output level. virtual void log(log_level_t level, const std::string & msg) { log(level, msg.c_str()); } //! \brief Log with format using an argument list. virtual void log(const char * fmt, va_list args); //! \brief Log with format using an argument with a specific output level. virtual void log(log_level_t level, const char * fmt, va_list args); //@} protected: log_level_t m_filter; //!< The current logging filter level. log_level_t m_level; //!< The current log output level. protected: //! \brief The base pure virtual logging function implemented by subclasses. virtual void _log(const char * msg)=0; }; /*! * \brief Wraps a set of static functions for easy global logging access. * * This class has a set of static methods that make it easy to access a global * logger instance without having to worry about extern symbols. It does this * by keeping a static member variable pointing at the singleton logger instance, * which is set with the setLogger() static method. * * There is also an inner utility class called SetOutputLevel that uses * C++ scoping rules to temporarily change the output logging level. When the * SetOutputLevel instance falls out of scope the output level is restored * to the previous value. */ class Log { public: //! \name Singleton logger access //@{ //! \brief Returns the current global logger singleton. static inline Logger * getLogger() { return s_logger; } //! \brief Sets the global logger singleton instance. static inline void setLogger(Logger * logger) { s_logger = logger; } //@} //! \name Logging //@{ //! \brief Log with format. static void log(const char * fmt, ...); //! \brief Log a string object. static void log(const std::string & msg); //! \brief Log with format at a specific output level. static void log(Logger::log_level_t level, const char * fmt, ...); //! \brief Log a string output at a specific output level. static void log(Logger::log_level_t level, const std::string & msg); //@} protected: static Logger * s_logger; //!< The single global logger instance. public: /*! * \brief Utility class to temporarily change the logging output level. * * This class will change the current logging output level of a given * logger instance. Then when it falls out of scope it will set the * level back to what it was originally. * * Use like this: * \code * // output level is some value here * { * Log::SetOutputLevel leveler(Logger::DEBUG); * // now output level is DEBUG * Log::log("my debug message 1"); * Log::log("my debug message 2"); * } * // output level is restored to previous value * \endcode */ class SetOutputLevel { public: //! \brief Default constructor. //! //! Saves the current logging output level of the global logger, //! as managed by the Log class, and sets the new level to \a level. SetOutputLevel(Logger::log_level_t level) : m_logger(Log::getLogger()), m_saved(Logger::INFO) { assert(m_logger); m_saved = m_logger->getOutputLevel(); m_logger->setOutputLevel(level); } //! \brief Constructor. //! //! Saves the current logging output level of \a logger and sets //! the new level to \a level. SetOutputLevel(Logger * logger, Logger::log_level_t level) : m_logger(logger), m_saved(logger->getOutputLevel()) { assert(m_logger); m_logger->setOutputLevel(level); } //! \brief Destructor. //! //! Restores the saved logging output level. ~SetOutputLevel() { m_logger->setOutputLevel(m_saved); } protected: Logger * m_logger; //!< The logger instance we're controlling. Logger::log_level_t m_saved; //!< Original logging output level. }; }; /*! * \brief Simple logger that writes to stdout. */ class StdoutLogger : public Logger { protected: //! \brief Logs the message to stdout. virtual void _log(const char * msg); }; #endif // _Logging_h_