#ifndef __JLOGGER__JMESSAGELOGGER__ #define __JLOGGER__JMESSAGELOGGER__ #include #include "JSystem/JNetwork.hh" #include "JSystem/JDateAndTime.hh" #include "JLang/JSharedPointer.hh" #include "JLogger/JLogger.hh" /** * \file * General purpose message reporting. * \author mdejong */ namespace JLOGGER {} namespace JPP { using namespace JLOGGER; } namespace JLOGGER { using JSYSTEM::getIPaddress; using JSYSTEM::getDateAndTime; using JLANG::JSharedPointer; /** * Message logging tag. */ static const std::string MESSAGE_TAG = std::string("MSG"); /** * Message logger. * * The class implements the following message functions: * * - debug(); * - warning(); * - error(); * - status(); * - notice(); * * The argument of these messages is an STL string.\n * The message reported consists of \ \ \ \ \\n * where the prefix is "DEBUG", "WARNING", "ERROR", "STATUS" or "NOTICE".\n * A debug level can be specified which is used to filter the message types for reporting.\n * The level OFF will cause the message logger to stop reporting any messages. * * Note that the JXXXStreamer classes can be used for STL ostream compatible message logging * (see JMessageStream.hh). */ class JMessageLogger : public JLogger { public: enum JLevel_t { OFF = -1, //!< No logging of messages ERROR = 0, //!< Error; always logged STATUS = 0, //!< Status; always logged WARNING = 1, //!< Warning NOTICE = 2, //!< Notice DEBUG = 3 //!< Debug }; typedef std::string JMessage_t; /** * Default constructor. */ JMessageLogger() : logger(), host (getIPaddress()), name ("") { setLevel(OFF); } /** * Constructor. * * \param __logger pointer to logger * \param __name name * \param __level debug level */ JMessageLogger(JLogger* __logger, const std::string& __name, const int __level = ERROR) : host (getIPaddress()), name (__name) { logger.reset(__logger); setLevel(__level); } /** * Reset logger. * * \param __logger pointer to logger */ void reset(JLogger* __logger = NULL) { logger.reset(__logger); } /** * Get debug level. * * \return debug level */ JLevel_t getLevel() { return level; } /** * Set debug level. * * \param __level debug level */ void setLevel(const int __level) { if (__level < 0) level = OFF; else if (__level == 0) level = ERROR; else if (__level == 1) level = WARNING; else if (__level == 2) level = NOTICE; else level = DEBUG; } /** * Set debug level. * * \param __level debug level */ void setLevel(const JLevel_t __level) { level = __level; } /** * Check validity of logger object. * * This operator returns the state of the logger object. * The object is valid if the logger object is ready for use, else the object is in-valid. * In case the object is in-valid, no messages will be reported. * * \return true if logger ready for use; else false */ bool is_valid() const { return logger.is_valid(); } /** * Report message. * * \param tag tag * \param message message */ virtual void typeout(const std::string& tag, const std::string& message) override { logger->typeout(tag, message); } #define TYPEOUT(LEVEL, MESSAGE) this->typeout(LEVEL, #LEVEL, MESSAGE) void debug (const JMessage_t& message) { TYPEOUT(DEBUG, message); } void warning(const JMessage_t& message) { TYPEOUT(WARNING, message); } void error (const JMessage_t& message) { TYPEOUT(ERROR, message); } void notice (const JMessage_t& message) { TYPEOUT(NOTICE, message); } void status (const JMessage_t& message) { TYPEOUT(STATUS, message); } #undef TYPEOUT protected: /** * Report message. * * \param __level level * \param __prefix prefix * \param __message message */ void typeout(const JLevel_t __level, const char* __prefix, const JMessage_t& __message) { if (is_valid() && __level <= level && !__message.empty()) { JMessage_t message; message += getDateAndTime(); message += " "; message += host; message += " "; message += name; message += " "; message += __prefix; message += " "; message += __message; typeout(MESSAGE_TAG, message); } } JSharedPointer logger; std::string host; std::string name; JLevel_t level; }; /** * Thread-safe message logger. * * This class aims to provide a thread-safe alternative to the JMessageLogger * class. Indeed it can transparently replace a JMessageLogger object * to be used in multi-thread environment. */ class JMessageLoggerThreadSafe : public JMessageLogger { public: /** * Default constructor. */ JMessageLoggerThreadSafe() : JMessageLogger() {} /** * Constructor. * * \param __logger pointer to logger * \param __name name * \param __level debug level */ JMessageLoggerThreadSafe(JLogger* __logger, const std::string& __name, const int __level = ERROR) : JMessageLogger(__logger, __name, __level) {} /** * Report message. * * \param tag tag * \param message message */ virtual void typeout(const std::string& tag, const std::string& message) override { JSYNCHRONIZATION::JMutex::JScopedLock lock(logger->mutex()); logger->typeout(tag, message); } }; } #endif