component.h \
configobject.cpp \
configobject.h \
- consolelogger.cpp \
- consolelogger.h \
dictionary.cpp \
dictionary.h \
event.cpp \
ringbuffer.h \
socket.cpp \
socket.h \
+ streamlogger.cpp \
+ streamlogger.h \
sysloglogger.cpp \
sysloglogger.h \
tcpclient.cpp \
} else {
try {
result = Main(m_Arguments);
- } catch (const std::exception& ex) {
+ } catch (const exception& ex) {
Application::m_Instance.reset();
Logger::Write(LogCritical, "base", "---");
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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 */
*
* @ingroup base
*/
-class I2_BASE_API Exception : public virtual std::exception
+class I2_BASE_API Exception : public virtual exception
{
public:
Exception(void)
#include <vector>
#include <set>
#include <iostream>
+#include <fstream>
#include <list>
#include <typeinfo>
#include <map>
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;
#include "component.h"
#include "threadpool.h"
#include "logger.h"
-#include "consolelogger.h"
+#include "streamlogger.h"
#include "sysloglogger.h"
#endif /* I2BASE_H */
using namespace icinga;
-vector<Logger::Ptr> Logger::m_Loggers;
+set<Logger::Ptr> Logger::m_Loggers;
/**
* Constructor for the logger class.
{
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);
}
/**
*/
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;
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;
private:
LogSeverity m_MinSeverity;
- static vector<Logger::Ptr> m_Loggers;
+ static set<Logger::Ptr> m_Loggers;
static void ForwardLogEntry(const LogEntry& entry);
};
*
* @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>();
~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);
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;
--- /dev/null
+#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;
+}
--- /dev/null
+#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 */
class SyslogLogger : public Logger
{
public:
+ typedef shared_ptr<SyslogLogger> Ptr;
+ typedef weak_ptr<SyslogLogger> WeakPtr;
+
SyslogLogger(LogSeverity minSeverity);
protected:
m_SyncingConfig = true;
object->Commit();
m_SyncingConfig = false;
- } catch (const std::exception&) {
+ } catch (const exception&) {
m_SyncingConfig = false;
throw;
}
m_SyncingConfig = true;
object->Unregister();
m_SyncingConfig = false;
- } catch (const std::exception&) {
+ } catch (const exception&) {
m_SyncingConfig = false;
throw;
}
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());
*/
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 */
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);
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");
if (!service.empty())
EndpointManager::GetInstance()->AddListener(service);
+ if (daemonize) {
+ Logger::Write(LogInformation, "icinga", "Daemonizing.");
+ Utility::Daemonize();
+ Logger::UnregisterLogger(consoleLogger);
+ }
+
RunEventLoop();
return EXIT_SUCCESS;
// 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();
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()));
}
}