]> granicus.if.org Git - icinga2/commitdiff
Implemented logging to files and made logging configurable.
authorGunnar Beutner <gunnar.beutner@netways.de>
Tue, 10 Jul 2012 13:14:45 +0000 (15:14 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Tue, 10 Jul 2012 13:14:45 +0000 (15:14 +0200)
18 files changed:
base/Makefile.am
base/application.cpp
base/consolelogger.cpp [deleted file]
base/consolelogger.h [deleted file]
base/exception.h
base/i2-base.h
base/logger.cpp
base/logger.h
base/socket.cpp
base/socket.h
base/streamlogger.cpp [new file with mode: 0644]
base/streamlogger.h [new file with mode: 0644]
base/sysloglogger.h
components/cibsync/cibsynccomponent.cpp
components/discovery/discoverycomponent.cpp
icinga/icingaapplication.cpp
icinga/jsonrpcendpoint.cpp
jsonrpc/jsonrpcclient.cpp

index d93337638506c980352f28dc4bd46e2467f6f09c..56580af66f5c02ac833696e9de6de7f978cbaf51 100644 (file)
@@ -11,8 +11,6 @@ libbase_la_SOURCES =  \
        component.h \
        configobject.cpp \
        configobject.h \
-       consolelogger.cpp \
-       consolelogger.h \
        dictionary.cpp \
        dictionary.h \
        event.cpp \
@@ -34,6 +32,8 @@ libbase_la_SOURCES =  \
        ringbuffer.h \
        socket.cpp \
        socket.h \
+       streamlogger.cpp \
+       streamlogger.h \
        sysloglogger.cpp \
        sysloglogger.h \
        tcpclient.cpp \
index 7d2d4c636ea52bbade5d6e18f3e0a8e158929cf6..c373b0c25b6c252431a4226aa290c8a9857cf3f6 100644 (file)
@@ -396,7 +396,7 @@ int Application::Run(int argc, char **argv)
        } else {
                try {
                        result = Main(m_Arguments);
-               } catch (const std::exception& ex) {
+               } catch (const exception& ex) {
                        Application::m_Instance.reset();
 
                        Logger::Write(LogCritical, "base", "---");
diff --git a/base/consolelogger.cpp b/base/consolelogger.cpp
deleted file mode 100644 (file)
index bd89b3a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "i2-base.h"
-
-using namespace icinga;
-
-/**
- * Constructor for the ConsoleLogger class.
- *
- * @param minSeverity Minimum severity for log messages.
- */
-ConsoleLogger::ConsoleLogger(LogSeverity minSeverity)
-       : Logger(minSeverity)
-{ }
-
-/**
- * Processes a log entry and outputs it to standard out.
- *
- * @param entry The log entry.
- */
-void ConsoleLogger::ProcessLogEntry(const LogEntry& entry)
-{
-       char timestamp[100];
-
-       string severityStr;
-       switch (entry.Severity) {
-               case LogDebug:
-                       severityStr = "debug";
-                       break;
-               case LogInformation:
-                       severityStr = "info";
-                       break;
-               case LogWarning:
-                       severityStr = "warning";
-                       break;
-               case LogCritical:
-                       severityStr = "critical";
-                       break;
-               default:
-                       assert(!"Invalid severity specified.");
-       }
-
-       tm tmnow = *localtime(&entry.Timestamp);
-
-       strftime(timestamp, sizeof(timestamp), "%Y/%m/%d %H:%M:%S", &tmnow);
-
-       std::cout << "[" << timestamp << "] "
-                << severityStr << "/" << entry.Facility << ": "
-                << entry.Message << std::endl;
-}
diff --git a/base/consolelogger.h b/base/consolelogger.h
deleted file mode 100644 (file)
index 22b5e06..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef CONSOLELOGGER_H
-#define CONSOLELOGGER_H
-
-namespace icinga
-{
-
-/**
- * A logger that logs to stdout.
- */
-class ConsoleLogger : public Logger
-{
-public:
-       ConsoleLogger(LogSeverity minSeverity);
-
-protected:
-       virtual void ProcessLogEntry(const LogEntry& entry);
-};
-
-}
-
-#endif /* CONSOLELOGGER_H */
index d614eb7cba7cfe5e68934d55032ffe5355c7cc01..8d041560ac0179564ca416a2292af7f4072ad327 100644 (file)
@@ -28,7 +28,7 @@ namespace icinga
  *
  * @ingroup base
  */
-class I2_BASE_API Exception : public virtual std::exception
+class I2_BASE_API Exception : public virtual exception
 {
 public:
        Exception(void)
index 2732a7df8fef4a2003c6e17beeafa233158e0460..eddb501d851da7e25a0d8f876844e20be2566c0c 100644 (file)
@@ -86,6 +86,7 @@
 #include <vector>
 #include <set>
 #include <iostream>
+#include <fstream>
 #include <list>
 #include <typeinfo>
 #include <map>
@@ -103,7 +104,10 @@ using std::pair;
 using std::deque;
 
 using std::stringstream;
+using std::ostream;
+using std::ofstream;
 
+using std::exception;
 using std::runtime_error;
 using std::logic_error;
 using std::invalid_argument;
@@ -169,7 +173,7 @@ using boost::system_time;
 #include "component.h"
 #include "threadpool.h"
 #include "logger.h"
-#include "consolelogger.h"
+#include "streamlogger.h"
 #include "sysloglogger.h"
 
 #endif /* I2BASE_H */
index 7d758858740853070bd467aeefe9556e4da6d570..3e90f3a3701442f29a7e37779398e9870f00a08c 100644 (file)
@@ -21,7 +21,7 @@
 
 using namespace icinga;
 
-vector<Logger::Ptr> Logger::m_Loggers;
+set<Logger::Ptr> Logger::m_Loggers;
 
 /**
  * Constructor for the logger class.
@@ -63,7 +63,19 @@ void Logger::RegisterLogger(const Logger::Ptr& logger)
 {
        assert(Application::IsMainThread());
 
-       m_Loggers.push_back(logger);
+       m_Loggers.insert(logger);
+}
+
+/**
+ * Unregisters a logger.
+ *
+ * @param logger The logger.
+ */
+void Logger::UnregisterLogger(const Logger::Ptr& logger)
+{
+       assert(Application::IsMainThread());
+
+       m_Loggers.erase(logger);
 }
 
 /**
@@ -83,7 +95,7 @@ LogSeverity Logger::GetMinSeverity(void) const
  */
 void Logger::ForwardLogEntry(const LogEntry& entry)
 {
-       vector<Logger::Ptr>::iterator it;
+       set<Logger::Ptr>::iterator it;
        for (it = m_Loggers.begin(); it != m_Loggers.end(); it++) {
                Logger::Ptr logger = *it;
 
index f3614d6f2caafeb42b3a93cd4b06e794a4fa5877..2fbfe0f4c9d653b0ed811b61099bcf0594d8d3b7 100644 (file)
@@ -57,12 +57,13 @@ public:
        typedef shared_ptr<Logger> Ptr;
        typedef weak_ptr<Logger> WeakPtr;
 
-       Logger(LogSeverity minSeverity = LogDebug);
+       Logger(LogSeverity minSeverity);
 
        static void Write(LogSeverity severity, const string& facility,
            const string& message);
 
        static void RegisterLogger(const Logger::Ptr& logger);
+       static void UnregisterLogger(const Logger::Ptr& logger);
 
 protected:
        virtual void ProcessLogEntry(const LogEntry& entry) = 0;
@@ -72,7 +73,7 @@ protected:
 private:
        LogSeverity m_MinSeverity;
 
-       static vector<Logger::Ptr> m_Loggers;
+       static set<Logger::Ptr> m_Loggers;
 
        static void ForwardLogEntry(const LogEntry& entry);
 };
index bdc2561eb86ef728eba33a12ff7038f70ecf7b2c..32a2c45efd1612768e6f54b0a11ab5604cac87f8 100644 (file)
@@ -156,7 +156,7 @@ int Socket::GetLastSocketError(void)
  *
  * @param ex An exception.
  */
-void Socket::HandleSocketError(const std::exception& ex)
+void Socket::HandleSocketError(const exception& ex)
 {
        if (!OnError.empty()) {
                Event::Ptr ev = boost::make_shared<Event>();
index 7878a8ddb61c16acac65e16d63d9ed55cce1664d..5b437f253c7983ff59878c91f4bdf1cbdf29d27b 100644 (file)
@@ -35,7 +35,7 @@ public:
 
        ~Socket(void);
 
-       boost::signal<void (const Socket::Ptr&, const std::exception&)> OnError;
+       boost::signal<void (const Socket::Ptr&, const exception&)> OnError;
        boost::signal<void (const Socket::Ptr&)> OnClosed;
 
        virtual void Start(void);
@@ -55,7 +55,7 @@ protected:
 
        int GetError(void) const;
        static int GetLastSocketError(void);
-       void HandleSocketError(const std::exception& ex);
+       void HandleSocketError(const exception& ex);
 
        virtual bool WantsToRead(void) const;
        virtual bool WantsToWrite(void) const;
diff --git a/base/streamlogger.cpp b/base/streamlogger.cpp
new file mode 100644 (file)
index 0000000..b1824a4
--- /dev/null
@@ -0,0 +1,85 @@
+#include "i2-base.h"
+
+using namespace icinga;
+
+/**
+ * Constructor for the StreamLogger class.
+ *
+ * @param minSeverity Minimum severity for log messages.
+ */
+StreamLogger::StreamLogger(LogSeverity minSeverity)
+       : Logger(minSeverity), m_Stream(NULL), m_OwnsStream(false)
+{ }
+
+/**
+ * Constructor for the StreamLogger class.
+ *
+ * @param stream The stream.
+ * @param minSeverity Minimum severity for log messages.
+ */
+StreamLogger::StreamLogger(ostream *stream, LogSeverity minSeverity)
+       : Logger(minSeverity), m_Stream(stream), m_OwnsStream(false)
+{ }
+
+/**
+ * Destructor for the StreamLogger class.
+ */
+StreamLogger::~StreamLogger(void)
+{
+       if (m_OwnsStream)
+               delete m_Stream;
+}
+
+void StreamLogger::OpenFile(const string& filename)
+{
+       ofstream *stream = new ofstream();
+
+       try {
+               stream->open(filename.c_str(), ofstream::out | ofstream::trunc);
+
+               if (!stream->good())
+                       throw runtime_error("Could not open logfile '" + filename + "'");
+       } catch (const exception&) {
+               delete stream;
+               throw;
+       }
+
+       m_Stream = stream;
+       m_OwnsStream = true;
+}
+
+/**
+ * Processes a log entry and outputs it to a stream.
+ *
+ * @param entry The log entry.
+ */
+void StreamLogger::ProcessLogEntry(const LogEntry& entry)
+{
+       char timestamp[100];
+
+       string severityStr;
+       switch (entry.Severity) {
+               case LogDebug:
+                       severityStr = "debug";
+                       break;
+               case LogInformation:
+                       severityStr = "info";
+                       break;
+               case LogWarning:
+                       severityStr = "warning";
+                       break;
+               case LogCritical:
+                       severityStr = "critical";
+                       break;
+               default:
+                       assert(!"Invalid severity specified.");
+       }
+
+       tm tmnow = *localtime(&entry.Timestamp);
+
+       strftime(timestamp, sizeof(timestamp), "%Y/%m/%d %H:%M:%S", &tmnow);
+
+       *m_Stream << "[" << timestamp << "] "
+                << severityStr << "/" << entry.Facility << ": "
+                << entry.Message << std::endl;
+}
diff --git a/base/streamlogger.h b/base/streamlogger.h
new file mode 100644 (file)
index 0000000..8da1a6b
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef STREAMLOGGER_H
+#define STREAMLOGGER_H
+
+namespace icinga
+{
+
+/**
+ * A logger that logs to stdout.
+ */
+class StreamLogger : public Logger
+{
+public:
+       typedef shared_ptr<StreamLogger> Ptr;
+       typedef weak_ptr<StreamLogger> WeakPtr;
+
+       StreamLogger(LogSeverity minSeverity);
+       StreamLogger(std::ostream *stream, LogSeverity minSeverity);
+       ~StreamLogger(void);
+
+       void OpenFile(const string& filename);
+protected:
+       virtual void ProcessLogEntry(const LogEntry& entry);
+
+private:
+       ostream *m_Stream;
+       bool m_OwnsStream;
+};
+
+}
+
+#endif /* STREAMLOGGER_H */
index f7676e36f9471c8280651cfb4c08878a5cd19925..0c9b648212b146bb526ca01edf6911d1ddd2c04d 100644 (file)
@@ -10,6 +10,9 @@ namespace icinga
 class SyslogLogger : public Logger
 {
 public:
+       typedef shared_ptr<SyslogLogger> Ptr;
+       typedef weak_ptr<SyslogLogger> WeakPtr;
+
        SyslogLogger(LogSeverity minSeverity);
 
 protected:
index a962fec159f9b29c101e2cbc4b22b6bcf725d6f2..7c0d27c472fd1c6b09508ab7fedbe44a70a92804 100644 (file)
@@ -263,7 +263,7 @@ void CIBSyncComponent::RemoteObjectCommittedHandler(const Endpoint::Ptr& sender,
                m_SyncingConfig = true;
                object->Commit();
                m_SyncingConfig = false;
-       } catch (const std::exception&) {
+       } catch (const exception&) {
                m_SyncingConfig = false;
                throw;
        }
@@ -293,7 +293,7 @@ void CIBSyncComponent::RemoteObjectRemovedHandler(const RequestMessage& request)
                        m_SyncingConfig = true;
                        object->Unregister();
                        m_SyncingConfig = false;
-               } catch (const std::exception&) {
+               } catch (const exception&) {
                        m_SyncingConfig = false;
                        throw;
                }
index be68e2b9100b26f82472f141b6ffadb924191fbb..f240d28bc445497f99de07308e9e1298867eef3e 100644 (file)
@@ -518,7 +518,7 @@ void DiscoveryComponent::DiscoveryTimerHandler(void)
                        try {
                                if (!info->Node.empty() && !info->Service.empty())
                                        endpointManager->AddConnection(info->Node, info->Service);
-                       } catch (const std::exception& ex) {
+                       } catch (const exception& ex) {
                                stringstream msgbuf;
                                msgbuf << "Exception while trying to reconnect to endpoint '" << endpoint->GetIdentity() << "': " << ex.what();;
                                Logger::Write(LogInformation, "discovery", msgbuf.str());
index 248cdeae4f315bcfa8e9eee5bd2c585a72bd94fe..7bc829b85faf7e8a736d9bea546b0340161e474b 100644 (file)
@@ -36,12 +36,9 @@ using namespace icinga;
  */
 int IcingaApplication::Main(const vector<string>& args)
 {
-       ConsoleLogger::Ptr consoleLogger = boost::make_shared<ConsoleLogger>(LogInformation);
+       StreamLogger::Ptr consoleLogger = boost::make_shared<StreamLogger>(&std::cout, LogInformation);
        Logger::RegisterLogger(consoleLogger);
 
-       SyslogLogger::Ptr syslogLogger = boost::make_shared<SyslogLogger>(LogInformation);
-       Logger::RegisterLogger(syslogLogger);
-
 #ifdef _WIN32
        Logger::Write(LogInformation, "icinga", "Icinga component loader");
 #else /* _WIN32 */
@@ -52,11 +49,64 @@ int IcingaApplication::Main(const vector<string>& args)
 
        if (args.size() < 2) {
                stringstream msgbuf;
-               msgbuf << "Syntax: " << args[0] << " <config-file>";
+               msgbuf << "Syntax: " << args[0] << " [-S] [-L logfile] [-d] [--] <config-file>";
                Logger::Write(LogInformation, "icinga", msgbuf.str());
                return EXIT_FAILURE;
        }
 
+       bool enableSyslog = false;
+       bool daemonize = false;
+       bool parseOpts = true;
+       string configFile;
+
+       /* TODO: clean up this mess; for now it will just have to do */
+       vector<string>::const_iterator it;
+       for (it = args.begin() + 1 ; it != args.end(); it++) {
+               string arg = *it;
+
+               /* ignore empty arguments */
+               if (arg.empty())
+                       continue;
+
+               if (arg == "--") {
+                       parseOpts = false;
+                       continue;
+               }
+
+               if (parseOpts && arg[0] == '-') {
+                       if (arg == "-S") {
+                               enableSyslog = true;
+                               continue;
+                       } else if (arg == "-L") {
+                               if (it + 1 == args.end())
+                                       throw invalid_argument("Option -L requires a parameter");
+
+                               StreamLogger::Ptr fileLogger = boost::make_shared<StreamLogger>(LogInformation);
+                               fileLogger->OpenFile(*(it + 1));
+                               Logger::RegisterLogger(fileLogger);
+
+                               it++;
+
+                               continue;
+                       } else {
+                               throw invalid_argument("Unknown option: " + arg);
+                       }
+               }
+
+               configFile = arg;
+
+               if (it + 1 != args.end())
+                       throw invalid_argument("Trailing command line arguments after config filename.");
+       }
+
+       if (configFile.empty())
+               throw invalid_argument("No config file was specified on the command line.");
+
+       if (enableSyslog) {
+               SyslogLogger::Ptr syslogLogger = boost::make_shared<SyslogLogger>(LogInformation);
+               Logger::RegisterLogger(syslogLogger);
+       }
+
        string componentDirectory = Utility::DirName(GetExePath()) + "/../lib/icinga2";
        AddComponentSearchDir(componentDirectory);
 
@@ -79,7 +129,7 @@ int IcingaApplication::Main(const vector<string>& args)
        fileComponentConfig->SetType("component");
        fileComponentConfig->SetName("configfile");
        fileComponentConfig->SetLocal(true);
-       fileComponentConfig->AddExpression("configFilename", OperatorSet, args[1]);
+       fileComponentConfig->AddExpression("configFilename", OperatorSet, configFile);
        fileComponentConfig->Compile()->Commit();
 
        ConfigObject::Ptr icingaConfig = ConfigObject::GetObject("application", "icinga");
@@ -111,6 +161,12 @@ int IcingaApplication::Main(const vector<string>& args)
        if (!service.empty())
                EndpointManager::GetInstance()->AddListener(service);
 
+       if (daemonize) {
+               Logger::Write(LogInformation, "icinga", "Daemonizing.");
+               Utility::Daemonize();
+               Logger::UnregisterLogger(consoleLogger);
+       }
+
        RunEventLoop();
 
        return EXIT_SUCCESS;
index 687ef863c6c4693e1f7a21c981a21c6b65ca1567..a1acc3c7beba77a47ad190c58abf7b31f71605c8 100644 (file)
@@ -127,7 +127,7 @@ void JsonRpcEndpoint::ClientClosedHandler(void)
        // TODO: persist events, etc., for now we just disable the endpoint
 }
 
-void JsonRpcEndpoint::ClientErrorHandler(const std::exception& ex)
+void JsonRpcEndpoint::ClientErrorHandler(const exception& ex)
 {
        stringstream message;
        message << "Error occured for JSON-RPC socket: Message=" << ex.what();
index 2d88ed336d957b8336f7d1727fe6877f6fb4b51c..e0bd2602c42fd957e6c0f4d81cc3eb8e89f0deab 100644 (file)
@@ -64,7 +64,7 @@ void JsonRpcClient::DataAvailableHandler(void)
                try {
                        message = MessagePart(jsonString);
                        OnNewMessage(GetSelf(), message);
-               } catch (const std::exception& ex) {
+               } catch (const exception& ex) {
                        Logger::Write(LogCritical, "jsonrpc", "Exception while processing message from JSON-RPC client: " + string(ex.what()));
                }
        }