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 */ 44class Logger 45{ 46public: 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 59public: 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 102protected: 103 log_level_t m_filter; //!< The current logging filter level. 104 log_level_t m_level; //!< The current log output level. 105 106protected: 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 */ 124class Log 125{ 126public: 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 151protected: 152 static Logger * s_logger; //!< The single global logger instance. 153 154public: 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 */ 219class StdoutLogger : public Logger 220{ 221protected: 222 //! \brief Logs the message to stdout. 223 virtual void _log(const char * msg); 224}; 225 226#endif // _Logging_h_ 227