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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/// 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 PRIO_FATAL, creates a Message with
* priority 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)
{
log(msg, PRIO_FATAL);
}
/** If the Logger's log level is at least PRIO_ERROR, creates a Message with priority
* 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)
{
log(msg, PRIO_ERROR);
}
/** If the Logger's log level is at least PRIO_WARNING, creates a Message with
* priority 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)
{
log(msg, PRIO_WARNING);
}
/** If the Logger's log level is at least PRIO_NOTICE, creates a Message with
* priority 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)
{
log(msg, PRIO_NOTICE);
}
/** If the Logger's log level is at least PRIO_INFORMATION, creates a Message with
* priority 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)
{
log(msg, PRIO_INFORMATION);
}
/** If the Logger's log level is at least PRIO_DEBUG, creates a Message with priority
* 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)
{
log(msg, PRIO_DEBUG);
}
/** 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
}
}
/** 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 PRIO_FATAL: m_log->fatal(message);
break;
case PRIO_ERROR: m_log->error(message);
break;
case PRIO_WARNING: m_log->warning(message);
break;
case PRIO_NOTICE: m_log->notice(message);
break;
case PRIO_INFORMATION: m_log->information(message);
break;
case 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 << e.what();
}
}
Gigg, Martyn Anthony
committed
} // namespace Kernel
Russell Taylor
committed
} // Namespace Mantid