Write early log messages to the Windows Event Log

When Icinga 2 is started as a service, the early log messages generated
until the FileLogger object is activated are lost and make it really
hard to debug issues that (only) occur when Icinga 2 reloads.

With this commit, these early log messages are written to the Windows
Event Log.
This commit is contained in:
Julian Brost 2021-04-08 13:49:53 +02:00
parent 6de9f58810
commit 05ca30a6a0
5 changed files with 50 additions and 1 deletions

View File

@ -9,6 +9,9 @@
#include "base/objectlock.hpp"
#include "base/context.hpp"
#include "base/scriptglobal.hpp"
#ifdef _WIN32
#include "base/windowseventloglogger.hpp"
#endif /* _WIN32 */
#include <iostream>
#include <utility>
@ -29,6 +32,7 @@ REGISTER_TYPE(Logger);
std::set<Logger::Ptr> Logger::m_Loggers;
std::mutex Logger::m_Mutex;
bool Logger::m_ConsoleLogEnabled = true;
std::atomic<bool> Logger::m_EarlyLoggingEnabled (true);
bool Logger::m_TimestampEnabled = true;
LogSeverity Logger::m_ConsoleLogSeverity = LogInformation;
@ -157,6 +161,14 @@ LogSeverity Logger::GetConsoleLogSeverity()
return m_ConsoleLogSeverity;
}
void Logger::DisableEarlyLogging() {
m_EarlyLoggingEnabled = false;
}
bool Logger::IsEarlyLoggingEnabled() {
return m_EarlyLoggingEnabled;
}
void Logger::DisableTimestamp()
{
m_TimestampEnabled = false;
@ -242,6 +254,12 @@ Log::~Log()
* then cout will not flush lines automatically. */
std::cout << std::flush;
}
#ifdef _WIN32
if (Logger::IsEarlyLoggingEnabled() && entry.Severity >= Logger::GetConsoleLogSeverity()) {
WindowsEventLogLogger::WriteToWindowsEventLog(entry);
}
#endif /* _WIN32 */
}
Log& Log::operator<<(const char *val)

View File

@ -67,6 +67,8 @@ public:
static void DisableConsoleLog();
static void EnableConsoleLog();
static bool IsConsoleLogEnabled();
static void DisableEarlyLogging();
static bool IsEarlyLoggingEnabled();
static void DisableTimestamp();
static void EnableTimestamp();
static bool IsTimestampEnabled();
@ -84,6 +86,7 @@ private:
static std::mutex m_Mutex;
static std::set<Logger::Ptr> m_Loggers;
static bool m_ConsoleLogEnabled;
static std::atomic<bool> m_EarlyLoggingEnabled;
static bool m_TimestampEnabled;
static LogSeverity m_ConsoleLogSeverity;
};

View File

@ -37,9 +37,21 @@ void WindowsEventLogLogger::StatsFunc(const Dictionary::Ptr& status, const Array
/**
* Processes a log entry and outputs it to the Windows Event Log.
*
* This function implements the interface expected by the Logger base class and passes
* the log entry to WindowsEventLogLogger::WriteToWindowsEventLog().
*
* @param entry The log entry.
*/
void WindowsEventLogLogger::ProcessLogEntry(const LogEntry& entry)
void WindowsEventLogLogger::ProcessLogEntry(const LogEntry& entry) {
WindowsEventLogLogger::WriteToWindowsEventLog(entry);
}
/**
* Writes a LogEntry object to the Windows Event Log.
*
* @param entry The log entry.
*/
void WindowsEventLogLogger::WriteToWindowsEventLog(const LogEntry& entry)
{
if (l_EventLog != nullptr) {
std::string message = Logger::SeverityToString(entry.Severity) + "/" + entry.Facility + ": " + entry.Message;

View File

@ -24,6 +24,8 @@ public:
static void StaticInitialize();
static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
static void WriteToWindowsEventLog(const LogEntry& entry);
protected:
void ProcessLogEntry(const LogEntry& entry) override;
void Flush() override;

View File

@ -675,6 +675,14 @@ bool ConfigItem::ActivateItems(const std::vector<ConfigItem::Ptr>& newItems, boo
return false;
});
/* Find the last logger type to be activated. */
Type::Ptr lastLoggerType = nullptr;
for (const Type::Ptr& type : types) {
if (Logger::TypeInstance->IsAssignableFrom(type)) {
lastLoggerType = type;
}
}
for (const Type::Ptr& type : types) {
for (const ConfigItem::Ptr& item : newItems) {
if (!item->m_Object)
@ -695,6 +703,12 @@ bool ConfigItem::ActivateItems(const std::vector<ConfigItem::Ptr>& newItems, boo
object->Activate(runtimeCreated, cookie);
}
// TODO: find a better name for silent
if (!silent && type == lastLoggerType) {
/* Disable early logging configuration once the last logger type was activated. */
Logger::DisableEarlyLogging();
}
}
if (!silent)