Make syslog facility handling reusable

The upcoming JournaldLogger will need the same syslog validation and
conversion logic, so factor it out from SyslogLogger to make it
reusable.

Also explicitely include syslog.h, which defines the syslog()
function.
This commit is contained in:
Tobias Deiminger 2021-09-11 13:48:11 +02:00 committed by haxtibal
parent 95cdc00ad4
commit de7808e32c
2 changed files with 64 additions and 43 deletions

View File

@ -5,6 +5,7 @@
#include "base/sysloglogger-ti.cpp"
#include "base/configtype.hpp"
#include "base/statsfunction.hpp"
#include <syslog.h>
using namespace icinga;
@ -12,11 +13,11 @@ REGISTER_TYPE(SyslogLogger);
REGISTER_STATSFUNCTION(SyslogLogger, &SyslogLogger::StatsFunc);
INITIALIZE_ONCE(&SyslogLogger::StaticInitialize);
INITIALIZE_ONCE(&SyslogHelper::StaticInitialize);
std::map<String, int> SyslogLogger::m_FacilityMap;
std::map<String, int> SyslogHelper::m_FacilityMap;
void SyslogLogger::StaticInitialize()
void SyslogHelper::StaticInitialize()
{
ScriptGlobal::Set("System.FacilityAuth", "LOG_AUTH", true);
ScriptGlobal::Set("System.FacilityAuthPriv", "LOG_AUTHPRIV", true);
@ -61,6 +62,44 @@ void SyslogLogger::StaticInitialize()
m_FacilityMap["LOG_UUCP"] = LOG_UUCP;
}
bool SyslogHelper::ValidateFacility(const String& facility)
{
if (m_FacilityMap.find(facility) == m_FacilityMap.end()) {
try {
Convert::ToLong(facility);
} catch (const std::exception&) {
return false;
}
}
return true;
}
int SyslogHelper::SeverityToNumber(LogSeverity severity)
{
switch (severity) {
case LogDebug:
return LOG_DEBUG;
case LogNotice:
return LOG_NOTICE;
case LogWarning:
return LOG_WARNING;
case LogCritical:
return LOG_CRIT;
case LogInformation:
default:
return LOG_INFO;
}
}
int SyslogHelper::FacilityToNumber(const String& facility)
{
auto it = m_FacilityMap.find(facility);
if (it != m_FacilityMap.end())
return it->second;
else
return Convert::ToLong(facility);
}
void SyslogLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
{
DictionaryData nodes;
@ -75,28 +114,14 @@ void SyslogLogger::StatsFunc(const Dictionary::Ptr& status, const Array::Ptr&)
void SyslogLogger::OnConfigLoaded()
{
ObjectImpl<SyslogLogger>::OnConfigLoaded();
String facilityString = GetFacility();
auto it = m_FacilityMap.find(facilityString);
if (it != m_FacilityMap.end())
m_Facility = it->second;
else
m_Facility = Convert::ToLong(facilityString);
m_Facility = SyslogHelper::FacilityToNumber(GetFacility());
}
void SyslogLogger::ValidateFacility(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
ObjectImpl<SyslogLogger>::ValidateFacility(lvalue, utils);
if (m_FacilityMap.find(lvalue()) == m_FacilityMap.end()) {
try {
Convert::ToLong(lvalue());
} catch (const std::exception&) {
BOOST_THROW_EXCEPTION(ValidationError(this, { "facility" }, "Invalid facility specified."));
}
}
if (!SyslogHelper::ValidateFacility(lvalue()))
BOOST_THROW_EXCEPTION(ValidationError(this, { "facility" }, "Invalid facility specified."));
}
/**
@ -106,27 +131,8 @@ void SyslogLogger::ValidateFacility(const Lazy<String>& lvalue, const Validation
*/
void SyslogLogger::ProcessLogEntry(const LogEntry& entry)
{
int severity;
switch (entry.Severity) {
case LogDebug:
severity = LOG_DEBUG;
break;
case LogNotice:
severity = LOG_NOTICE;
break;
case LogWarning:
severity = LOG_WARNING;
break;
case LogCritical:
severity = LOG_CRIT;
break;
case LogInformation:
default:
severity = LOG_INFO;
break;
}
syslog(severity | m_Facility, "%s", entry.Message.CStr());
syslog(SyslogHelper::SeverityToNumber(entry.Severity) | m_Facility,
"%s", entry.Message.CStr());
}
void SyslogLogger::Flush()

View File

@ -10,6 +10,23 @@
namespace icinga
{
/**
* Helper class to handle syslog facility strings and numbers.
*
* @ingroup base
*/
class SyslogHelper final
{
public:
static void StaticInitialize();
static bool ValidateFacility(const String& facility);
static int SeverityToNumber(LogSeverity severity);
static int FacilityToNumber(const String& facility);
private:
static std::map<String, int> m_FacilityMap;
};
/**
* A logger that logs to syslog.
*
@ -21,14 +38,12 @@ public:
DECLARE_OBJECT(SyslogLogger);
DECLARE_OBJECTNAME(SyslogLogger);
static void StaticInitialize();
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
void OnConfigLoaded() override;
void ValidateFacility(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
protected:
static std::map<String, int> m_FacilityMap;
int m_Facility;
void ProcessLogEntry(const LogEntry& entry) override;