///@file Logger.hpp
#ifndef __LOGGER_HPP_INCLUDED__
#define __LOGGER_HPP_INCLUDED__
#include<iostream>
/// An enumeration of various logging categories
enum LogCategory
{
LC_INFO, /// Info - messages are sent to std::clog
LC_ERROR, /// Error - messages are sent to std::err
LC_DEBUG, /// Debug - messages are sent to std::cout
LC_EXPLOIT /// Exploit - messages are (temp) sent to std::cout
/// TODO: Send messages via IRC or Email
};
/**
* @class Logger
* @brief A simple logging utility, not a performance solution, but quick and easy.
* @author Luc
* @version 1
*/
class Logger
{
public:
/// Retrieves a logger instance of the specified category
/**
* @param category
* The category to log under
* @return
* A logger instance of the specified category
* @throw
* This method may throw a std::logic_error if a logger of the specified category does not exist
* @note
* Any exceptional behavior can be prevented at compile-time.
*/
static Logger& getInstance(LogCategory category)
{
static Logger info(LC_INFO), error(LC_ERROR), debug(LC_DEBUG), exploit(LC_EXPLOIT);
switch(category)
{
case LC_INFO:
return info;
case LC_ERROR:
return error;
case LC_DEBUG:
return debug;
case LC_EXPLOIT:
return exploit;
default:
throw std::logic_error("Logger::getInstance - No existing logger of the specified category exists.");
}
}
/// Inserts the provided data into the specified logger's stream
/**
* @tparam T
* The type of the data to insert
* @param logger
* The logger whose stream to use
* @param data
* The data to insert
* @return
* A reference to the specified logger is returned
* @throw
* This method may throw a std::bad_alloc if the stream insertion fails due to a low memory situation.
*/
template<typename T>
friend Logger& operator<<(Logger& logger, const T& data)
{
logger.log(data);
return logger;
}
private:
/// Non-copyable
Logger(const Logger& rhs);
/// Non-assignable
Logger operator=(const Logger& rhs);
/// Constructs a Logger
/**
* @note
* This class is intentionally not publicly constructable.
* @param category
* The type of logging that this Logger will do
* @throw
* This method may throw a std::bad_alloc if construction fails due to a low memory situation
*/
Logger(LogCategory category)
: category_(category)
{
}
/// Logs the specified data in the way that is specified
/**
* @tparam T
* The type of the data to log
* @param data
* The data to log
* @throw
* This method may throw a std::logic_error if a logger of the specified category does not exist<br>
* or if the logging fails due to a low memory situation
*/
template<typename T>
void log(const T& data)
{
switch(this->category_)
{
case LC_INFO:
std::clog << data << std::flush;
break;
case LC_ERROR:
std::cerr << data << std::flush;
break;
case LC_DEBUG:
std::cout << data << std::flush;
break;
case LC_EXPLOIT:
std::cout << data << std::flush;
break;
default:
throw std::logic_error("Logger::log - No existing logger of the specified category exists.");
}
}
/// The logging category that this logger covers
LogCategory category_;
};
#endif
Everyone needs a little logging every now and then.
I manually write my own logs in text files. I really should integrate some sort of automatic logging system, but I don't really have the time to plan out a design.
I really like this chicken, and salad sandwich I'm eating.
I have been writing my log for ages (it supports Xml and plain text files, as well as ostreams and anything else which can output lines of text). However, even as I add more and more features to it, I am starting to wonder if I should just use Boost.Logging or log4cpp or something.
What are people's opinions on this matter?
EDIT: Also, my log class is not a singleton. I thought long and hard about this, but I am making all the classes in my library non singleton, with an optional "singletonised" version.