xref: /netbsd-src/external/bsd/elftosb/dist/common/Logging.h (revision 993229b6fea628ff8b1fa09146c80b0cfb2768eb)
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.
Logger()61 	Logger() : m_filter(INFO), m_level(INFO) {}
62 
63 	//! \brief Destructor.
~Logger()64 	virtual ~Logger() {}
65 
66 	//! \name Logging levels
67 	//@{
68 	//! \brief Changes the logging level to \a level.
setFilterLevel(log_level_t level)69 	inline void setFilterLevel(log_level_t level) { m_filter = level; }
70 
71 	//! \brief Returns the current logging filter level.
getFilterLevel()72 	inline log_level_t getFilterLevel() const { return m_filter; }
73 
74 	//! \brief Changes the logging output level to \a level.
setOutputLevel(log_level_t level)75 	inline void setOutputLevel(log_level_t level) { m_level = level; }
76 
77 	//! \brief Returns the current logging output level.
getOutputLevel()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.
log(const std::string & msg)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.
log(log_level_t level,const std::string & msg)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.
getLogger()130 	static inline Logger * getLogger() { return s_logger; }
131 
132 	//! \brief Sets the global logger singleton instance.
setLogger(Logger * logger)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.
SetOutputLevel(Logger::log_level_t 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.
SetOutputLevel(Logger * logger,Logger::log_level_t 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.
~SetOutputLevel()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