From 8843ecc5b9762631f07828d562f2309defd2e956 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 16 Dec 2006 18:47:38 +0000 Subject: Initial implementation of the logging framework. --- lib/common/Logging.cpp | 192 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/common/Logging.h | 148 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 lib/common/Logging.cpp create mode 100644 lib/common/Logging.h (limited to 'lib/common') diff --git a/lib/common/Logging.cpp b/lib/common/Logging.cpp new file mode 100644 index 00000000..0e77f252 --- /dev/null +++ b/lib/common/Logging.cpp @@ -0,0 +1,192 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: Logging.cpp +// Purpose: Generic logging core routines implementation +// Created: 2006/12/16 +// +// -------------------------------------------------------------------------- + +#include "Box.h" + +#ifdef HAVE_SYSLOG_H + #include +#endif + +#include "Logging.h" + +bool Loggers::sLogToSyslog = false; +bool Loggers::sLogToConsole = false; +bool Loggers::sContextSet = false; + +void Loggers::ToSyslog(bool enabled) +{ + if (!sLogToSyslog && enabled) + { + Add(&sSyslog); + } + + if (sLogToSyslog && !enabled) + { + Remove(&sSyslog); + } + + sLogToSyslog = enabled; +} + +void Loggers::ToConsole(bool enabled) +{ + if (!sLogToConsole && enabled) + { + Add(&sConsole); + } + + if (sLogToConsole && !enabled) + { + Remove(&sConsole); + } + + sLogToConsole = enabled; +} + +void Loggers::FilterConsole(Log::Level level) +{ + sConsole.Filter(level); +} + +void Loggers::FilterSyslog(Log::Level level) +{ + sSyslog.Filter(level); +} + +void Loggers::Add(Logger* pNewLogger) +{ + for (std::vector::iterator i = sLoggers.begin(); + i != sLoggers.end(); i++) + { + if (*i == pNewLogger) + { + return; + } + } + + sLoggers.insert(sLoggers.begin(), pNewLogger); +} + +void Loggers::Remove(Logger* pOldLogger) +{ + for (std::vector::iterator i = sLoggers.begin(); + i != sLoggers.end(); i++) + { + if (*i == pOldLogger) + { + sLoggers.erase(i); + return; + } + } +} + +void Loggers::Log(Log::Level level, const std::string& rFile, + const std::string& rLine, const std::string& rMessage) +{ + std::string newMessage; + + if (sContextSet) + { + newMessage += "[" + sContext + "] "; + } + + newMessage += rMessage; + + for (std::vector::iterator i = sLoggers.begin(); + i != sLoggers.end(); i++) + { + bool result = (*i)->Log(level, rFile, rLine, newMessage); + if (!result) + { + return; + } + } +} + +void Loggers::SetContext(std::string context) +{ + sContext = context; + sContextSet = true; +} + +void Loggers::ClearContext() +{ + sContextSet = false; +} + +void Loggers::SetProgramName(const std::string& rProgramName) +{ + for (std::vector::iterator i = sLoggers.begin(); + i != sLoggers.end(); i++) + { + (*i)->SetProgramName(rProgramName); + } +} + +bool Console::Log(Log::Level level, const std::string& rFile, + const std::string& rLine, std::string& rMessage) +{ + if (level > GetLevel()) + { + return true; + } + + FILE* target = stdout; + + if (level <= Log::WARNING) + { + target = stderr; + } + + fprintf(target, "%s", rMessage.c_str()); + + return true; +} + +bool Syslog::Log(Log::Level level, const std::string& rFile, + const std::string& rLine, std::string& rMessage) +{ + if (level > GetLevel()) + { + return true; + } + + int syslogLevel = LOG_ERR; + + switch(level) + { + case Log::NOTHING: /* fall through */ + case Log::FATAL: syslogLevel = LOG_CRIT; break; + case Log::ERROR: syslogLevel = LOG_ERR; break; + case Log::WARNING: syslogLevel = LOG_WARNING; break; + case Log::INFO: syslogLevel = LOG_INFO; break; + case Log::TRACE: /* fall through */ + case Log::EVERYTHING: syslogLevel = LOG_DEBUG; break; + } + + syslog(syslogLevel, "%s", rMessage.c_str()); + + return true; +} + +Syslog::Syslog() +{ + ::openlog("Box Backup", LOG_PID, LOG_LOCAL6); +} + +Syslog::~Syslog() +{ + ::closelog(); +} + +void Syslog::SetProgramName(const std::string& rProgramName) +{ + ::closelog(); + ::openlog(rProgramName.c_str(), LOG_PID, LOG_LOCAL6); +} diff --git a/lib/common/Logging.h b/lib/common/Logging.h new file mode 100644 index 00000000..9fb1be4a --- /dev/null +++ b/lib/common/Logging.h @@ -0,0 +1,148 @@ +// -------------------------------------------------------------------------- +// +// File +// Name: Logging.h +// Purpose: Generic logging core routines declarations and macros +// Created: 2006/12/16 +// +// -------------------------------------------------------------------------- + +#ifndef LOGGING__H +#define LOGGING__H + +#include +#include + +#define BOX_LOG(level, stuff) \ +{ \ + if(Log::sMaxLoggingLevelForAnyOutput >= level) \ + std::ostringstream line; \ + line << stuff; \ + Log::Write(level, __FILE__, __LINE__, line.str()); \ + } \ +} + +#define BOX_FATAL(stuff) BOX_LOG(Log::FATAL, stuff) +#define BOX_ERROR(stuff) BOX_LOG(Log::ERROR, stuff) +#define BOX_WARNING(stuff) BOX_LOG(Log::WARNING, stuff) +#define BOX_INFO(stuff) BOX_LOG(Log::INFO, stuff) +#if defined NDEBUG && ! defined COMPILE_IN_TRACES + #define BOX_TRACE(stuff) +#else + #define BOX_TRACE(stuff) BOX_LOG(Log::TRACE, stuff) +#endif + +namespace Log +{ + enum Level { NOTHING = 1, FATAL, ERROR, WARNING, INFO, TRACE, EVERYTHING }; +} + +// -------------------------------------------------------------------------- +// +// Class +// Name: Logger +// Purpose: Abstract class (interface) for log targets +// Created: 2006/12/16 +// +// -------------------------------------------------------------------------- + +class Logger +{ + private: + Log::Level mCurrentLevel; + + public: + Logger() : mCurrentLevel(Log::WARNING) { } + virtual ~Logger() { } + + virtual bool Log(Log::Level level, const std::string& rFile, + const std::string& rLine, std::string& rMessage) = 0; + + void Filter(Log::Level level) + { + mCurrentLevel = level; + } + + virtual const char* GetType() = 0; + Log::Level GetLevel() { return mCurrentLevel; } + + virtual void SetProgramName(const std::string& rProgramName) = 0; +}; + +// -------------------------------------------------------------------------- +// +// Class +// Name: Console +// Purpose: Console logging target +// Created: 2006/12/12 +// +// -------------------------------------------------------------------------- + +class Console : public Logger +{ + public: + virtual bool Log(Log::Level level, const std::string& rFile, + const std::string& rLine, std::string& rMessage); + virtual const char* GetType() { return "Console"; } + virtual void SetProgramName(const std::string& rProgramName) { } +}; + +// -------------------------------------------------------------------------- +// +// Class +// Name: Syslog +// Purpose: Syslog (or Windows Event Viewer) logging target +// Created: 2006/12/12 +// +// -------------------------------------------------------------------------- + +class Syslog : public Logger +{ + public: + Syslog(); + virtual ~Syslog(); + + virtual bool Log(Log::Level level, const std::string& rFile, + const std::string& rLine, std::string& rMessage); + virtual const char* GetType() { return "Syslog"; } + virtual void SetProgramName(const std::string& rProgramName); +}; + +// -------------------------------------------------------------------------- +// +// Class +// Name: Log +// Purpose: Static logging helper, keeps track of enabled loggers +// and distributes log messages to them. +// Created: 2006/12/12 +// +// -------------------------------------------------------------------------- + +class Loggers +{ + private: + static std::vector sLoggers; + static bool sLogToSyslog, sLogToConsole; + static std::string sContext; + static bool sContextSet; + static Console sConsole; + static Syslog sSyslog; + static Log::Level sGlobalLevel; + + public: + static void Init(const std::string& rProgramName); + static void ToSyslog (bool enabled); + static void ToConsole (bool enabled); + static void FilterSyslog (Log::Level level); + static void FilterConsole (Log::Level level); + static void Add (Logger* pNewLogger); + static void Remove (Logger* pOldLogger); + static void Log(Log::Level level, const std::string& rFile, + const std::string& rLine, const std::string& rMessage); + static void SetContext(std::string context); + static void ClearContext(); + static void SetGlobalLevel(Log::Level level) { sGlobalLevel = level; } + static void SetProgramName(const std::string& rProgramName); +}; + +#endif // LOGGING__H -- cgit v1.2.3