diff --git a/base/logger.cpp b/base/logger.cpp index 3e90f3a37..5699b12d3 100644 --- a/base/logger.cpp +++ b/base/logger.cpp @@ -103,3 +103,33 @@ void Logger::ForwardLogEntry(const LogEntry& entry) logger->ProcessLogEntry(entry); } } + +string Logger::SeverityToString(LogSeverity severity) +{ + switch (severity) { + case LogDebug: + return "debug"; + case LogInformation: + return "information"; + case LogWarning: + return "warning"; + case LogCritical: + return "critical"; + default: + throw invalid_argument("Invalid severity."); + } +} + +LogSeverity Logger::StringToSeverity(const string& severity) +{ + if (severity == "debug") + return LogDebug; + else if (severity == "information") + return LogInformation; + else if (severity == "warning") + return LogWarning; + else if (severity == "critical") + return LogCritical; + else + throw invalid_argument("Invalid severity: " + severity); +} diff --git a/base/logger.h b/base/logger.h index 2fbfe0f4c..bcbb22051 100644 --- a/base/logger.h +++ b/base/logger.h @@ -65,6 +65,9 @@ public: static void RegisterLogger(const Logger::Ptr& logger); static void UnregisterLogger(const Logger::Ptr& logger); + static string SeverityToString(LogSeverity severity); + static LogSeverity StringToSeverity(const string& severity); + protected: virtual void ProcessLogEntry(const LogEntry& entry) = 0; diff --git a/base/streamlogger.cpp b/base/streamlogger.cpp index b1824a4b5..7126cc5cd 100644 --- a/base/streamlogger.cpp +++ b/base/streamlogger.cpp @@ -57,29 +57,11 @@ 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 << ": " + << Logger::SeverityToString(entry.Severity) << "/" << entry.Facility << ": " << entry.Message << std::endl; } diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 85d847176..5d98f1687 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -42,8 +42,20 @@ IcingaApplication::IcingaApplication(void) */ int IcingaApplication::Main(const vector& args) { - StreamLogger::Ptr consoleLogger = boost::make_shared(&std::cout, LogInformation); - Logger::RegisterLogger(consoleLogger); + /* register handler for 'log' config objects */ + static ConfigObject::Set::Ptr logObjects = boost::make_shared(ConfigObject::GetAllObjects(), ConfigObject::MakeTypePredicate("log")); + logObjects->OnObjectAdded.connect(boost::bind(&IcingaApplication::NewLogHandler, this, _2)); + logObjects->OnObjectCommitted.connect(boost::bind(&IcingaApplication::NewLogHandler, this, _2)); + logObjects->OnObjectRemoved.connect(boost::bind(&IcingaApplication::DeletedLogHandler, this, _2)); + logObjects->Start(); + + /* create console logger */ + ConfigItemBuilder::Ptr consoleLogConfig = boost::make_shared(); + consoleLogConfig->SetType("log"); + consoleLogConfig->SetName("console"); + consoleLogConfig->SetLocal(true); + consoleLogConfig->AddExpression("type", OperatorSet, "console"); + consoleLogConfig->Compile()->Commit(); #ifdef _WIN32 Logger::Write(LogInformation, "icinga", "Icinga component loader"); @@ -159,6 +171,17 @@ int IcingaApplication::Main(const vector& args) icingaConfig->GetProperty("service", &m_Service); icingaConfig->GetProperty("pidpath", &m_PidPath); + string logpath; + if (icingaConfig->GetProperty("logpath", &logpath)) { + ConfigItemBuilder::Ptr fileLogConfig = boost::make_shared(); + fileLogConfig->SetType("log"); + fileLogConfig->SetName("main"); + fileLogConfig->SetLocal(true); + fileLogConfig->AddExpression("type", OperatorSet, "file"); + fileLogConfig->AddExpression("path", OperatorSet, logpath); + fileLogConfig->Compile()->Commit(); + } + UpdatePidFile(GetPidPath()); if (!GetCertificateFile().empty() && !GetCAFile().empty()) { @@ -182,7 +205,6 @@ int IcingaApplication::Main(const vector& args) ClosePidFile(); Utility::Daemonize(); UpdatePidFile(GetPidPath()); - Logger::UnregisterLogger(consoleLogger); } RunEventLoop(); @@ -208,6 +230,54 @@ void IcingaApplication::NewComponentHandler(const ConfigObject::Ptr& object) LoadComponent(path, object); } +void IcingaApplication::NewLogHandler(const ConfigObject::Ptr& object) +{ + /* don't allow replicated config objects */ + if (!object->IsLocal()) + throw runtime_error("'log' objects must be 'local'"); + + Logger::Ptr logger; + if (object->GetTag("logger", &logger)) + Logger::UnregisterLogger(logger); + + string type; + if (!object->GetProperty("type", &type)) + throw invalid_argument("'log' object must have a 'type' property"); + + string strSeverity; + LogSeverity severity = LogInformation; + if (object->GetProperty("severity", &strSeverity)) + severity = Logger::StringToSeverity(strSeverity); + + if (type == "syslog") { + logger = boost::make_shared(severity); + } else if (type == "file") { + string path; + if (!object->GetProperty("path", &path)) + throw invalid_argument("'log' object of type 'file' must have a 'path' property"); + + StreamLogger::Ptr slogger = boost::make_shared(severity); + slogger->OpenFile(path); + + logger = slogger; + } else if (type == "console") { + logger = boost::make_shared(&std::cout, severity); + } else { + throw runtime_error("Unknown log type: " + type); + } + + object->SetTag("logger", logger); + + Logger::RegisterLogger(logger); +} + +void IcingaApplication::DeletedLogHandler(const ConfigObject::Ptr& object) +{ + Logger::Ptr logger; + if (object->GetTag("logger", &logger)) + Logger::UnregisterLogger(logger); +} + IcingaApplication::Ptr IcingaApplication::GetInstance(void) { return static_pointer_cast(Application::GetInstance()); diff --git a/icinga/icingaapplication.h b/icinga/icingaapplication.h index b8d5f9062..bf15401f0 100644 --- a/icinga/icingaapplication.h +++ b/icinga/icingaapplication.h @@ -61,6 +61,9 @@ private: void NewComponentHandler(const ConfigObject::Ptr& object); void DeletedComponentHandler(const ConfigObject::Ptr& object); + + void NewLogHandler(const ConfigObject::Ptr& object); + void DeletedLogHandler(const ConfigObject::Ptr& object); }; }