Newer
Older
Gigg, Martyn Anthony
committed
#include "MantidKernel/ThreadSafeLogStream.h"
Gigg, Martyn Anthony
committed
#include <Poco/Message.h>
#ifdef _MSC_VER
// Disable a flood of warnings about inheriting from std streams
// See http://connect.microsoft.com/VisualStudio/feedback/details/733720/inheriting-from-std-fstream-produces-c4250-warning
#pragma warning( push )
#pragma warning( disable : 4250 )
#endif
#ifdef _MSC_VER
#pragma warning( pop )
#endif
Nick Draper
committed
#include <iostream>
Russell Taylor
committed
{
namespace Kernel
{
namespace
{
// We only need a single NullStream object
Poco::NullOutputStream NULL_STREAM;
}
/** Constructor
* @param name :: The class name invoking this logger
*/
Logger::Logger(const std::string& name)
: m_log(&Poco::Logger::get(name)), m_logStream(new ThreadSafeLogStream(*m_log)),
m_levelOffset(0), m_enabled(true)
Gigg, Martyn Anthony
committed
{
}
/// Destructor
Logger::~Logger()
{
delete m_logStream;
}
Gigg, Martyn Anthony
committed
/**
* @param name The new name
*/
void Logger::setName(const std::string & name)
{
auto *logger = &Poco::Logger::get(name);
auto *logStream = new ThreadSafeLogStream(*logger); // don't swap if this throws
using std::swap;
swap(m_log, logger);
swap(m_logStream, logStream);
delete logStream;
}
/** 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()
{
return getLogStream(Priority::PRIO_FATAL);
}
/** 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()
{
return getLogStream(Priority::PRIO_ERROR);
}
/** 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()
{
return getLogStream(Priority::PRIO_WARNING);
}
/** 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()
{
return getLogStream(Priority::PRIO_NOTICE);
}
/** 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()
{
return getLogStream(Priority::PRIO_INFORMATION);
}
/** 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()
{
return getLogStream(Priority::PRIO_DEBUG);
}
Gigg, Martyn Anthony
committed
/** Shuts down the logging framework and releases all Loggers.
* Static method.
*/
void Logger::shutdown()
{
try
Gigg, Martyn Anthony
committed
{
// Release the POCO loggers
Poco::Logger::shutdown();
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);
}
/**
* @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
{
Gigg, Martyn Anthony
committed
{
case Poco::Message::PRIO_FATAL: m_log->fatal(message);
break;
case Poco::Message::PRIO_CRITICAL: m_log->critical(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;
case Poco::Message::PRIO_TRACE: m_log->trace(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();
}
}
/**
* Log a given message at a given priority
* @param priority :: The priority level
*/
std::ostream& Logger::getLogStream(Logger::Priority priority)
{
if( !m_enabled ) return NULL_STREAM;
switch( applyLevelOffset(priority) )
{
case Poco::Message::PRIO_FATAL: return m_logStream->fatal();
break;
case Poco::Message::PRIO_CRITICAL: return m_logStream->critical();
break;
case Poco::Message::PRIO_ERROR: return m_logStream->error();
break;
case Poco::Message::PRIO_WARNING: return m_logStream->warning();
break;
case Poco::Message::PRIO_NOTICE: return m_logStream->notice();
break;
case Poco::Message::PRIO_INFORMATION:return m_logStream->information();
break;
case Poco::Message::PRIO_DEBUG: return m_logStream->debug();
break;
default:
return NULL_STREAM;
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
}
}
/**
* Adjust a log priority level based off the m_levelOffset
* @param proposedLevel :: The proposed level
* @returns The offseted level
*/
Logger::Priority Logger::applyLevelOffset(Logger::Priority proposedLevel)
{
int retVal = proposedLevel;
//fast exit is offset is 0
if (m_levelOffset==0)
{
return proposedLevel;
}
else
{
retVal += m_levelOffset;
if (retVal < static_cast<int>(Priority::PRIO_FATAL))
{
retVal = Priority::PRIO_FATAL;
}
else if (retVal > static_cast<int>(Priority::PRIO_TRACE))
{
retVal = Priority::PRIO_TRACE;
}
}
//Logger::Priority p(retVal);
return static_cast<Logger::Priority>(retVal);
}
Gigg, Martyn Anthony
committed
/**
* Sets the Logger's log offset level.
* @param level :: The level offset to use
*/
void Logger::setLevelOffset(int level)
{
m_levelOffset = level;
}
/**
* Gets the Logger's log offset level.
* @returns The offset level
*/ /// Gets the Logger's log offset level.
int Logger::getLevelOffset() const
Gigg, Martyn Anthony
committed
} // namespace Kernel
Russell Taylor
committed
} // Namespace Mantid