namespace utils
{
/**
* A very simple logger that writes messages to a log file.
* If the log file is not set, the messages are routed to the standard output
* or the standard error depending on the level of the message.
* By default, the messages will be timestamped but the logger can be
* configured to not prefix the messages with a timestamp.
*
* Limitations:
* - not thread-safe.
*
* Example of use:
*
*
* \#include "logger.h"
*
* int main()
* {
* using namespace utils;
*
* Logger::setLogFile("/path/to/logfile");
*
* // log messages using helper macros.
* LOG_DEBUG("level: " << 3)
* LOG_INFO("init sound")
* LOG_WARN("not implemented")
* LOG_ERROR("resource not found")
* LOG_FATAL("unable to init graphics")
*
* // log messages using APIs.
* std::ostringstream os;
* os << "level: " << 3;
* Logger::output(os.str(), Logger::Debug);
*
* Logger::output("init sound", Logger::Info);
* Logger::output("not implemented", Logger::Warn);
* Logger::output("resource not found", Logger::Error);
* Logger::output("unable to init graphics", Logger::Fatal);
*
* return 0;
* }
*
*/
class Logger
{
public:
enum Level
{
Fatal = 0,
Error,
Warn,
Info,
Debug
};
static void initialize(const std::string &logFile);
/**
* Sets the log file.
*
* This method will open the log file for writing, the former file
* contents are removed.
*
* @param logFile the log file name (may include path).
* @param append whether the file is cleaned up before logging in.
*
* @exception std::ios::failure if the log file could not be opened.
*/
static void setLogFile(const std::string &logFile, bool append = false);
/**
* Add/removes the timestamp.
*
* @param flag if true, a log message will always be timestamped
* (default = true).
*/
static void setTimestamp(bool flag = true)
{ mHasTimestamp = flag; }
/**
* Sets tee mode.
*
* @param flag if true, write messages to both the standard (or error)
* output and the log file (if set) (default = true).
*/
static void setTeeMode(bool flag = true)
{ mTeeMode = flag; }
/**
* Sets the verbosity level of the logger.
*
* @param verbosity is the level of verbosity.
*/
static void setVerbosity(Level verbosity)
{ mVerbosity = verbosity; }
/**
* Enable logrotation based on the maximum filesize given in
* setMaxLogfileSize.
*
* @param enable Set to true to enable logrotation.
*/
static void setLogRotation(bool enable)
{ mLogRotation = enable; }
/**
* Sets the maximum size of a logfile before logrotation occurs.
*
* @param kiloBytes Maximum size of logfile in bytes. Defaults to 1MB.
*/
static void setMaxLogfileSize(long kiloBytes = 1024)
{ mMaxFileSize = kiloBytes; }
/**
* Sets whether the logfile switches when changing date.
*
* @param switchLogEachDay Keeps whether the parameter is activated.
*/
static void setSwitchLogEachDay(bool switchLogEachDay)
{ mSwitchLogEachDay = switchLogEachDay; }
/**
* Logs a generic message.
*
* @param msg the message to log.
*
* @param atVerbosity the minimum verbosity level
* to log this
*
* @exception std::ios::failure.
*/
static void output(const std::string &msg, Level atVerbosity);
static Level mVerbosity; /**< Verbosity level. */
private:
static bool mHasTimestamp; /**< Timestamp flag. */
static bool mTeeMode; /**< Tee mode flag. */
static std::string mFilename; /**< Name of the current logfile. */
/** Enable rotation of logfiles by size. */
static bool mLogRotation;
/** Maximum size of current logfile in bytes */
static long mMaxFileSize;
/** Sets whether the logfile switches when changing date. */
static bool mSwitchLogEachDay;
/**
* Logs a generic message.
*
* @param os the output stream.
* @param msg the message to log.
* @param prefix the message prefix.
*
* @exception std::ios::failure.
*/
static void output(std::ostream &os, const std::string &msg,
const char *prefix);
/**
* Switch the log file based on a maximum size
* and/or and a date change.
*/
static void switchLogs();
};
/**
* Class for temporarily debugging things that are actually not interesting
* to include in the log.
*
* It is used for automatically ending with a newline, putting spaces in
* between different parameters and quoting strings.
*/
class Debug
{
public:
~Debug() { std::cout << std::endl; }
template
Debug &operator << (T t)
{
std::cout << t << " ";
return *this;
}
};
template <>
inline Debug &Debug::operator << (const std::string &t)
{
std::cout << "\"" << t << "\" ";
return *this;
}
} // namespace utils
// HELPER MACROS
#define LOG(level, msg) \
do if (::utils::Logger::mVerbosity >= ::utils::Logger::level) { \
std::ostringstream os; \
os << msg; \
::utils::Logger::output(os.str(), ::utils::Logger::level); \
} while (0)
#define LOG_DEBUG(msg) LOG(Debug, msg)
#define LOG_INFO(msg) LOG(Info, msg)
#define LOG_WARN(msg) LOG(Warn, msg)
#define LOG_ERROR(msg) LOG(Error, msg)
#define LOG_FATAL(msg) LOG(Fatal, msg)
/**
* Returns an instance of the debug class for printing out a line.
*
* Usage: debug() << "testing" << a << b;
*/
inline ::utils::Debug debug() { return ::utils::Debug(); }
#endif // LOGGER_H