Implemented 'log' config object and 'logpath' property for the 'application' object.

This commit is contained in:
Gunnar Beutner 2012-07-13 09:03:22 +02:00
parent e5ae9dd94e
commit 6473416352
5 changed files with 110 additions and 22 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -42,8 +42,20 @@ IcingaApplication::IcingaApplication(void)
*/
int IcingaApplication::Main(const vector<string>& args)
{
StreamLogger::Ptr consoleLogger = boost::make_shared<StreamLogger>(&std::cout, LogInformation);
Logger::RegisterLogger(consoleLogger);
/* register handler for 'log' config objects */
static ConfigObject::Set::Ptr logObjects = boost::make_shared<ConfigObject::Set>(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<ConfigItemBuilder>();
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<string>& args)
icingaConfig->GetProperty("service", &m_Service);
icingaConfig->GetProperty("pidpath", &m_PidPath);
string logpath;
if (icingaConfig->GetProperty("logpath", &logpath)) {
ConfigItemBuilder::Ptr fileLogConfig = boost::make_shared<ConfigItemBuilder>();
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<string>& 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<SyslogLogger>(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<StreamLogger>(severity);
slogger->OpenFile(path);
logger = slogger;
} else if (type == "console") {
logger = boost::make_shared<StreamLogger>(&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<IcingaApplication>(Application::GetInstance());

View File

@ -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);
};
}