Newer
Older
Gigg, Martyn Anthony
committed
#include "MantidKernel/ThreadSafeLogStream.h"
Gigg, Martyn Anthony
committed
#include <Poco/Message.h>
Nick Draper
committed
#include <iostream>
Russell Taylor
committed
{
namespace Kernel
{
// Initialize the static members
Logger::LoggerList* Logger::m_loggerList = NULL;
Gigg, Martyn Anthony
committed
Mutex* Logger::mutexLoggerList = NULL;
Poco::NullOutputStream* Logger::m_nullStream = NULL;
/** Constructor
* @param name :: The class name invoking this logger
*/
Logger::Logger(const std::string& name) : m_enabled(true)
Gigg, Martyn Anthony
committed
{
m_name = name;
m_log=&Poco::Logger::get(m_name);
m_logStream = new Mantid::Kernel::ThreadSafeLogStream(*m_log);
}
/// Destructor
Logger::~Logger()
{
delete (m_logStream);
}
Gigg, Martyn Anthony
committed
/// Sets the Loggername to a new value.
void Logger::setName(std::string newName)
{
//delete the log stream
delete (m_logStream);
//reassign m_log
m_name = newName;
m_log = &Poco::Logger::get(m_name);
//create a new Logstream
m_logStream = new Mantid::Kernel::ThreadSafeLogStream(*m_log);
}
/** Returns true if the log is enabled
*
* @retval true - logging is enabled
* @retval false - all messages are ignored.
*/
bool Logger::getEnabled() const
{
return m_enabled;
}
/** set if the logging is enabled
*
* @param enabled :: true - logging is enabled, false - all messages are ignored.
*/
void Logger::setEnabled(const bool enabled)
{
m_enabled = enabled;
}
/** If the Logger's log level is at least Poco::Message::PRIO_FATAL, creates a Message with
* priority Poco::Message::PRIO_FATAL and the given message text and sends it to the attached channel.
*
* @param msg :: The message to log.
*/
void Logger::fatal(const std::string& msg)
{
}
/** If the Logger's log level is at least Poco::Message::PRIO_ERROR, creates a Message with priority
* Poco::Message::PRIO_ERROR and the given message text and sends it to the attached channel.
*
* @param msg :: The message to log.
*/
void Logger::error(const std::string& msg)
{
}
/** If the Logger's log level is at least Poco::Message::PRIO_WARNING, creates a Message with
* priority Poco::Message::PRIO_WARNING and the given message text and sends it to the attached channel.
*
* @param msg :: The message to log.
*/
void Logger::warning(const std::string& msg)
{
}
/** If the Logger's log level is at least Poco::Message::PRIO_NOTICE, creates a Message with
* priority Poco::Message::PRIO_NOTICE and the given message text and sends it to the attached channel.
*
* @param msg :: The message to log.
*/
void Logger::notice(const std::string& msg)
{
}
/** If the Logger's log level is at least Poco::Message::PRIO_INFORMATION, creates a Message with
* priority Poco::Message::PRIO_INFORMATION and the given message text and sends it to the
* attached channel.
*
* @param msg :: The message to log.
*/
void Logger::information(const std::string& msg)
{
}
/** If the Logger's log level is at least Poco::Message::PRIO_DEBUG, creates a Message with priority
* Poco::Message::PRIO_DEBUG and the given message text and sends it to the attached channel.
*
* @param msg :: The message to log.
*/
void Logger::debug(const std::string& msg)
{
}
/** Logs the given message at debug level, followed by the data in buffer.
*
* The data in buffer is written in canonical hex+ASCII form:
* Offset (4 bytes) in hexadecimal, followed by sixteen space-separated,
* two column, hexadecimal bytes, followed by the same sixteen bytes as
* ASCII characters.
* For bytes outside the range 32 .. 127, a dot is printed.
* Note all Dump messages go out at Debug message level
*
* @param msg :: The message to log
* @param buffer :: the binary data to log
* @param length :: The length of the binaary data to log
*/
void Logger::dump(const std::string& msg, const void* buffer, std::size_t length)
{
if(m_enabled)
Gigg, Martyn Anthony
committed
{
try
{
m_log->dump(msg,buffer,length);
}
catch (std::exception& e)
{
//failures in logging are not allowed to throw exceptions out of the logging class
std::cerr << e.what();
}
Gigg, Martyn Anthony
committed
}
}
Gigg, Martyn Anthony
committed
/** Returns true if at least the given log level is set.
* @param level :: The logging level it is best to use the Logger::Priority enum (7=debug, 6=information, 4=warning, 3=error, 2=critical, 1=fatal)
* @return true if at least the given log level is set.
*/
bool Logger::is(int level) const
{
bool retVal = false;
try
Gigg, Martyn Anthony
committed
{
retVal = m_log->is(level);
Gigg, Martyn Anthony
committed
}
catch (std::exception& e)
Gigg, Martyn Anthony
committed
{
//failures in logging are not allowed to throw exceptions out of the logging class
std::cerr << e.what();
Gigg, Martyn Anthony
committed
}
return retVal;
}
Gigg, Martyn Anthony
committed
void Logger::setLevel(int level)
{
try
Gigg, Martyn Anthony
committed
{
m_log->setLevel(level);
Gigg, Martyn Anthony
committed
}
catch (std::exception& e)
Gigg, Martyn Anthony
committed
{
//failures in logging are not allowed to throw exceptions out of the logging class
std::cerr << e.what();
Gigg, Martyn Anthony
committed
}
}
Gigg, Martyn Anthony
committed
/// Sets the Logger's log level using a symbolic value.
///
/// @param level :: Valid values are: fatal, critical, error, warning, notice, information, debug
void Logger::setLevel(const std::string& level)
{
try
Gigg, Martyn Anthony
committed
{
m_log->setLevel(level);
Gigg, Martyn Anthony
committed
}
catch (std::exception& e)
Gigg, Martyn Anthony
committed
{
//failures in logging are not allowed to throw exceptions out of the logging class
std::cerr << e.what();
Gigg, Martyn Anthony
committed
}
}
Gigg, Martyn Anthony
committed
int Logger::getLevel() const
{
return m_log->getLevel();
}
/** This class implements an ostream interface to the Logger for fatal messages.
*
* The stream's buffer appends all characters written to it
* to a string. As soon as a CR or LF (std::endl) is written,
* the string is sent to the Logger.
* @returns an std::ostream reference.
*/
std::ostream& Logger::fatal()
{
if (m_enabled)
Gigg, Martyn Anthony
committed
{
return m_logStream->fatal();
Gigg, Martyn Anthony
committed
}
else
Gigg, Martyn Anthony
committed
{
return *m_nullStream;
Gigg, Martyn Anthony
committed
}
}
/** This class implements an ostream interface to the Logger for error messages.
*
* The stream's buffer appends all characters written to it
* to a string. As soon as a CR or LF (std::endl) is written,
* the string is sent to the Logger.
* @returns an std::ostream reference.
*/
std::ostream& Logger::error()
{
if (m_enabled)
Gigg, Martyn Anthony
committed
{
return m_logStream->error();
Gigg, Martyn Anthony
committed
}
else
Gigg, Martyn Anthony
committed
{
return *m_nullStream;
Gigg, Martyn Anthony
committed
}
}
/** This class implements an ostream interface to the Logger for warning messages.
*
* The stream's buffer appends all characters written to it
* to a string. As soon as a CR or LF (std::endl) is written,
* the string is sent to the Logger.
* @returns an std::ostream reference.
*/
std::ostream& Logger::warning()
{
if (m_enabled)
Gigg, Martyn Anthony
committed
{
return m_logStream->warning();
Gigg, Martyn Anthony
committed
}
else
Gigg, Martyn Anthony
committed
{
return *m_nullStream;
Gigg, Martyn Anthony
committed
}
}
/** This class implements an ostream interface to the Logger for notice messages.
*
* The stream's buffer appends all characters written to it
* to a string. As soon as a CR or LF (std::endl) is written,
* the string is sent to the Logger.
* @returns an std::ostream reference.
*/
std::ostream& Logger::notice()
{
if (m_enabled)
Gigg, Martyn Anthony
committed
{
return m_logStream->notice();
Gigg, Martyn Anthony
committed
}
else
Gigg, Martyn Anthony
committed
{
return *m_nullStream;
Gigg, Martyn Anthony
committed
}
}
/** This class implements an ostream interface to the Logger for information messages.
*
* The stream's buffer appends all characters written to it
* to a string. As soon as a CR or LF (std::endl) is written,
* the string is sent to the Logger.
* @returns an std::ostream reference.
*/
std::ostream& Logger::information()
{
if (m_enabled)
Gigg, Martyn Anthony
committed
{
return m_logStream->information();
Gigg, Martyn Anthony
committed
}
else
Gigg, Martyn Anthony
committed
{
return *m_nullStream;
Gigg, Martyn Anthony
committed
}
}
/** This class implements an ostream interface to the Logger for debug messages.
*
* The stream's buffer appends all characters written to it
* to a string. As soon as a CR or LF (std::endl) is written,
* the string is sent to the Logger.
* @returns an std::ostream reference.
*/
std::ostream& Logger::debug()
{
if (m_enabled)
Gigg, Martyn Anthony
committed
{
return m_logStream->debug();
Gigg, Martyn Anthony
committed
}
else
Gigg, Martyn Anthony
committed
{
return *m_nullStream;
Gigg, Martyn Anthony
committed
}
}
Gigg, Martyn Anthony
committed
/** releases resources and deletes this object.
*/
void Logger::release()
{
destroy(*this);
}
/** Deletes the logger and clears it from the cache.
*
* @param logger :: The logger to destroy.
*/
void Logger::destroy(Logger& logger)
{
if (m_loggerList)
Gigg, Martyn Anthony
committed
{
try
Gigg, Martyn Anthony
committed
{ mutexLoggerList->lock(); }
catch(Poco::SystemException &)
{}
LoggerList::iterator it = m_loggerList->find(&logger);
if (it != m_loggerList->end())
Gigg, Martyn Anthony
committed
{
delete(*it);
m_loggerList->erase(it);
Gigg, Martyn Anthony
committed
}
try
Gigg, Martyn Anthony
committed
{ mutexLoggerList->unlock(); }
catch(Poco::SystemException &)
Gigg, Martyn Anthony
committed
}
}
Gigg, Martyn Anthony
committed
/** Shuts down the logging framework and releases all Loggers.
* Static method.
*/
void Logger::shutdown()
{
try
Gigg, Martyn Anthony
committed
{
//first release the POCO loggers
Poco::Logger::shutdown();
//now delete our static cache of loggers
if (m_loggerList)
Gigg, Martyn Anthony
committed
{
for (LoggerList::iterator it = m_loggerList->begin(); it != m_loggerList->end(); ++it)
{
delete(*it);
}
delete m_loggerList;
m_loggerList = 0;
Gigg, Martyn Anthony
committed
}
//delete the NullChannel
if (m_nullStream)
Gigg, Martyn Anthony
committed
{
delete(m_nullStream);
m_nullStream=0;
Gigg, Martyn Anthony
committed
}
Gigg, Martyn Anthony
committed
// Finally delete the mutex
delete mutexLoggerList;
Gigg, Martyn Anthony
committed
}
catch (std::exception& e)
Gigg, Martyn Anthony
committed
{
//failures in logging are not allowed to throw exceptions out of the logging class
std::cerr << e.what();
Gigg, Martyn Anthony
committed
}
}
/** Sets the log level for all Loggers created so far, including the root logger.
* @param level :: the priority level to set for the loggers
*/
void Logger::setLevelForAll(const int level)
{
// "" is the root logger
Poco::Logger::setLevel("",level);
}
/** Returns a reference to the Logger with the given name.
* This logger is stored until in a static list until it is destroyed, released or Logger::shutdown is called.
*
* @param name :: The name of the logger to use - this is usually the class name.
* @return a reference to the Logger with the given name.
*/
Logger& Logger::get(const std::string& name)
{
Logger* pLogger = new Logger(name);
Gigg, Martyn Anthony
committed
// MG: This method can be called to initialize static logger which means
// it may get called before mutexLoggerList has been initialized, i.e. the
// usual static initialization order problem.
if( mutexLoggerList == NULL ) mutexLoggerList = new Mutex();
try
Gigg, Martyn Anthony
committed
{ mutexLoggerList->lock(); }
catch(Poco::SystemException &)
Gigg, Martyn Anthony
committed
//assert the nullSteam
if(!m_nullStream)
Gigg, Martyn Anthony
committed
{
m_nullStream = new Poco::NullOutputStream;
Gigg, Martyn Anthony
committed
}
//assert the loggerlist
if (!m_loggerList)
Gigg, Martyn Anthony
committed
{
m_loggerList = new LoggerList;
Gigg, Martyn Anthony
committed
}
//insert the newly created logger
m_loggerList->insert(pLogger);
Gigg, Martyn Anthony
committed
try
Gigg, Martyn Anthony
committed
{ mutexLoggerList->unlock(); }
catch(Poco::SystemException &)
Gigg, Martyn Anthony
committed
return *pLogger;
}
Gigg, Martyn Anthony
committed
/**
* Log a given message at a given priority
* @param message :: The message to log
* @param priority :: The priority level
*/
void Logger::log(const std::string message, Logger::Priority priority)
{
if( !m_enabled ) return;
Gigg, Martyn Anthony
committed
try
{
switch( priority )
Gigg, Martyn Anthony
committed
{
case Poco::Message::PRIO_FATAL: m_log->fatal(message);
break;
case Poco::Message::PRIO_ERROR: m_log->error(message);
break;
case Poco::Message::PRIO_WARNING: m_log->warning(message);
break;
case Poco::Message::PRIO_NOTICE: m_log->notice(message);
break;
case Poco::Message::PRIO_INFORMATION: m_log->information(message);
break;
case Poco::Message::PRIO_DEBUG: m_log->debug(message);
break;
default:
break;
Gigg, Martyn Anthony
committed
}
}
catch(std::exception& e)
{
// Failures in logging are not allowed to throw exceptions out of the logging class
std::cerr << "Error in logging framework: " << e.what();
}
}
Gigg, Martyn Anthony
committed
} // namespace Kernel
Russell Taylor
committed
} // Namespace Mantid