Home | History | Annotate | Line # | Download | only in common
      1 /*
      2  * File:	Logging.h
      3  *
      4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
      5  * See included license file for license details.
      6  */
      7 #if !defined(_Logging_h_)
      8 #define _Logging_h_
      9 
     10 #include <string>
     11 #include <assert.h>
     12 #include <stdarg.h>
     13 
     14 /*!
     15  * \brief Base logger class.
     16  *
     17  * There are two types of logging levels that are used by this class. First
     18  * there is the filter level. Any log message that is assigned a level
     19  * higher than the current filter level is discarded. Secondly there is the
     20  * current output level. Log messages that do not have their own level
     21  * use the current output level to determine if they should be shown or
     22  * not.
     23  *
     24  * The two methods setFilterLevel() and setOutputLevel() set the filter
     25  * and default output logging levels, respectively. There are corresponding
     26  * getter methods as well. Both the filter and output levels are
     27  * initialized to #INFO during object construction.
     28  *
     29  * Most use of the logger classes is expected to be through the Log
     30  * class. It provides static logging methods that call through to a global
     31  * singleton logger instance. There is also a Log::SetOutputLevel utility
     32  * class that makes it extremely easiy to temporarily change the default
     33  * output logging level.
     34  *
     35  * Of all the overloaded log() methods in this class, none of them are
     36  * really expected to be reimplemented by subclasses. Instead, there is
     37  * the single protected _log() method that takes a simple string pointer.
     38  * The other log methods all wind up calling _log(), so it provides a
     39  * single point to override. In fact, _log() is pure virtual, so subclasses
     40  * must implement it.
     41  *
     42  * \see Log
     43  */
     44 class Logger
     45 {
     46 public:
     47 	//! \brief Logging levels.
     48 	enum log_level_t
     49 	{
     50 		URGENT = 0,	//!< The lowest level, for messages that must always be logged.
     51 		ERROR,		//!< For fatal error messages.
     52 		WARNING,	//!< For non-fatal warning messages.
     53 		INFO,		//!< The normal log level, for status messages.
     54 		INFO2,		//!< For verbose status messages.
     55 		DEBUG,		//!< For internal reporting.
     56 		DEBUG2		//!< Highest log level; verbose debug logging.
     57 	};
     58 
     59 public:
     60 	//! \brief Default constructor.
     61 	Logger() : m_filter(INFO), m_level(INFO) {}
     62 
     63 	//! \brief Destructor.
     64 	virtual ~Logger() {}
     65 
     66 	//! \name Logging levels
     67 	//@{
     68 	//! \brief Changes the logging level to \a level.
     69 	inline void setFilterLevel(log_level_t level) { m_filter = level; }
     70 
     71 	//! \brief Returns the current logging filter level.
     72 	inline log_level_t getFilterLevel() const { return m_filter; }
     73 
     74 	//! \brief Changes the logging output level to \a level.
     75 	inline void setOutputLevel(log_level_t level) { m_level = level; }
     76 
     77 	//! \brief Returns the current logging output level.
     78 	inline log_level_t getOutputLevel() const { return m_level; }
     79 	//@}
     80 
     81 	//! \name Logging
     82 	//@{
     83 	//! \brief Log with format.
     84 	virtual void log(const char * fmt, ...);
     85 
     86 	//! \brief Log a string object.
     87 	virtual void log(const std::string & msg) { log(msg.c_str()); }
     88 
     89 	//! \brief Log with format at a specific output level.
     90 	virtual void log(log_level_t level, const char * fmt, ...);
     91 
     92 	//! \brief Log a string output at a specific output level.
     93 	virtual void log(log_level_t level, const std::string & msg) { log(level, msg.c_str()); }
     94 
     95 	//! \brief Log with format using an argument list.
     96 	virtual void log(const char * fmt, va_list args);
     97 
     98 	//! \brief Log with format using an argument with a specific output level.
     99 	virtual void log(log_level_t level, const char * fmt, va_list args);
    100 	//@}
    101 
    102 protected:
    103 	log_level_t m_filter;	//!< The current logging filter level.
    104 	log_level_t m_level;	//!< The current log output level.
    105 
    106 protected:
    107 	//! \brief The base pure virtual logging function implemented by subclasses.
    108 	virtual void _log(const char * msg)=0;
    109 };
    110 
    111 /*!
    112  * \brief Wraps a set of static functions for easy global logging access.
    113  *
    114  * This class has a set of static methods that make it easy to access a global
    115  * logger instance without having to worry about extern symbols. It does this
    116  * by keeping a static member variable pointing at the singleton logger instance,
    117  * which is set with the setLogger() static method.
    118  *
    119  * There is also an inner utility class called SetOutputLevel that uses
    120  * C++ scoping rules to temporarily change the output logging level. When the
    121  * SetOutputLevel instance falls out of scope the output level is restored
    122  * to the previous value.
    123  */
    124 class Log
    125 {
    126 public:
    127 	//! \name Singleton logger access
    128 	//@{
    129 	//! \brief Returns the current global logger singleton.
    130 	static inline Logger * getLogger() { return s_logger; }
    131 
    132 	//! \brief Sets the global logger singleton instance.
    133 	static inline void setLogger(Logger * logger) { s_logger = logger; }
    134 	//@}
    135 
    136 	//! \name Logging
    137 	//@{
    138 	//! \brief Log with format.
    139 	static void log(const char * fmt, ...);
    140 
    141 	//! \brief Log a string object.
    142 	static void log(const std::string & msg);
    143 
    144 	//! \brief Log with format at a specific output level.
    145 	static void log(Logger::log_level_t level, const char * fmt, ...);
    146 
    147 	//! \brief Log a string output at a specific output level.
    148 	static void log(Logger::log_level_t level, const std::string & msg);
    149 	//@}
    150 
    151 protected:
    152 	static Logger * s_logger;	//!< The single global logger instance.
    153 
    154 public:
    155 	/*!
    156 	 * \brief Utility class to temporarily change the logging output level.
    157 	 *
    158 	 * This class will change the current logging output level of a given
    159 	 * logger instance. Then when it falls out of scope it will set the
    160 	 * level back to what it was originally.
    161 	 *
    162 	 * Use like this:
    163 	 * \code
    164 	 *		// output level is some value here
    165 	 *		{
    166 	 *			Log::SetOutputLevel leveler(Logger::DEBUG);
    167 	 *			// now output level is DEBUG
    168 	 *			Log::log("my debug message 1");
    169 	 *			Log::log("my debug message 2");
    170 	 *		}
    171 	 *		// output level is restored to previous value
    172 	 * \endcode
    173 	 */
    174 	class SetOutputLevel
    175 	{
    176 	public:
    177 		//! \brief Default constructor.
    178 		//!
    179 		//! Saves the current logging output level of the global logger,
    180 		//! as managed by the Log class, and sets the new level to \a level.
    181 		SetOutputLevel(Logger::log_level_t level)
    182 		:	m_logger(Log::getLogger()), m_saved(Logger::INFO)
    183 		{
    184 			assert(m_logger);
    185 			m_saved = m_logger->getOutputLevel();
    186 			m_logger->setOutputLevel(level);
    187 		}
    188 
    189 		//! \brief Constructor.
    190 		//!
    191 		//! Saves the current logging output level of \a logger and sets
    192 		//! the new level to \a level.
    193 		SetOutputLevel(Logger * logger, Logger::log_level_t level)
    194 		:	m_logger(logger), m_saved(logger->getOutputLevel())
    195 		{
    196 			assert(m_logger);
    197 			m_logger->setOutputLevel(level);
    198 		}
    199 
    200 		//! \brief Destructor.
    201 		//!
    202 		//! Restores the saved logging output level.
    203 		~SetOutputLevel()
    204 		{
    205 			m_logger->setOutputLevel(m_saved);
    206 		}
    207 
    208 	protected:
    209 		Logger * m_logger;	//!< The logger instance we're controlling.
    210 		Logger::log_level_t m_saved;	//!< Original logging output level.
    211 	};
    212 
    213 };
    214 
    215 
    216 /*!
    217  * \brief Simple logger that writes to stdout.
    218  */
    219 class StdoutLogger : public Logger
    220 {
    221 protected:
    222 	//! \brief Logs the message to stdout.
    223 	virtual void _log(const char * msg);
    224 };
    225 
    226 #endif // _Logging_h_
    227