220 lines
7.6 KiB
C++
220 lines
7.6 KiB
C++
/*
|
|
* 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 <string>
|
|
#include <assert.h>
|
|
#include <stdarg.h>
|
|
|
|
/*!
|
|
* \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_
|