summaryrefslogtreecommitdiff
path: root/lib/common
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2006-12-16 18:47:38 +0000
committerChris Wilson <chris+github@qwirx.com>2006-12-16 18:47:38 +0000
commit8843ecc5b9762631f07828d562f2309defd2e956 (patch)
tree087a926dc961d8b9bc75d8c0071c32872df45b6c /lib/common
parent1e14bb0876a81f4168ea028dddd53e8a81c1c727 (diff)
Initial implementation of the logging framework.
Diffstat (limited to 'lib/common')
-rw-r--r--lib/common/Logging.cpp192
-rw-r--r--lib/common/Logging.h148
2 files changed, 340 insertions, 0 deletions
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 <syslog.h>
+#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<Logger*>::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<Logger*>::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<Logger*>::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<Logger*>::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 <sstream>
+#include <vector>
+
+#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<Logger*> 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