diff --git a/lib/base/logger.cpp b/lib/base/logger.cpp index 531839ca3..0be7279b2 100644 --- a/lib/base/logger.cpp +++ b/lib/base/logger.cpp @@ -12,6 +12,7 @@ #ifdef _WIN32 #include "base/windowseventloglogger.hpp" #endif /* _WIN32 */ +#include #include #include @@ -35,6 +36,8 @@ bool Logger::m_ConsoleLogEnabled = true; std::atomic Logger::m_EarlyLoggingEnabled (true); bool Logger::m_TimestampEnabled = true; LogSeverity Logger::m_ConsoleLogSeverity = LogInformation; +std::mutex Logger::m_UpdateMinLogSeverityMutex; +Atomic Logger::m_MinLogSeverity (LogDebug); INITIALIZE_ONCE([]() { ScriptGlobal::Set("System.LogDebug", LogDebug, true); @@ -51,8 +54,12 @@ void Logger::Start(bool runtimeCreated) { ObjectImpl::Start(runtimeCreated); - std::unique_lock lock(m_Mutex); - m_Loggers.insert(this); + { + std::unique_lock lock(m_Mutex); + m_Loggers.insert(this); + } + + UpdateMinLogSeverity(); } void Logger::Stop(bool runtimeRemoved) @@ -62,6 +69,8 @@ void Logger::Stop(bool runtimeRemoved) m_Loggers.erase(this); } + UpdateMinLogSeverity(); + ObjectImpl::Stop(runtimeRemoved); } @@ -139,11 +148,15 @@ LogSeverity Logger::StringToSeverity(const String& severity) void Logger::DisableConsoleLog() { m_ConsoleLogEnabled = false; + + UpdateMinLogSeverity(); } void Logger::EnableConsoleLog() { m_ConsoleLogEnabled = true; + + UpdateMinLogSeverity(); } bool Logger::IsConsoleLogEnabled() @@ -163,6 +176,8 @@ LogSeverity Logger::GetConsoleLogSeverity() void Logger::DisableEarlyLogging() { m_EarlyLoggingEnabled = false; + + UpdateMinLogSeverity(); } bool Logger::IsEarlyLoggingEnabled() { @@ -184,6 +199,13 @@ bool Logger::IsTimestampEnabled() return m_TimestampEnabled; } +void Logger::SetSeverity(const String& value, bool suppress_events, const Value& cookie) +{ + ObjectImpl::SetSeverity(value, suppress_events, cookie); + + UpdateMinLogSeverity(); +} + void Logger::ValidateSeverity(const Lazy& lvalue, const ValidationUtils& utils) { ObjectImpl::ValidateSeverity(lvalue, utils); @@ -195,14 +217,42 @@ void Logger::ValidateSeverity(const Lazy& lvalue, const ValidationUtils& } } -Log::Log(LogSeverity severity, String facility, const String& message) - : m_Severity(severity), m_Facility(std::move(facility)) +void Logger::UpdateMinLogSeverity() { - m_Buffer << message; + std::unique_lock lock (m_UpdateMinLogSeverityMutex); + auto result (LogNothing); + + for (auto& logger : Logger::GetLoggers()) { + ObjectLock llock (logger); + + if (logger->IsActive()) { + result = std::min(result, logger->GetMinSeverity()); + } + } + + if (Logger::IsConsoleLogEnabled()) { + result = std::min(result, Logger::GetConsoleLogSeverity()); + } + +#ifdef _WIN32 + if (Logger::IsEarlyLoggingEnabled()) { + result = std::min(result, LogCritical); + } +#endif /* _WIN32 */ + + m_MinLogSeverity.store(result); +} + +Log::Log(LogSeverity severity, String facility, const String& message) + : Log(severity, std::move(facility)) +{ + if (!m_IsNoOp) { + m_Buffer << message; + } } Log::Log(LogSeverity severity, String facility) - : m_Severity(severity), m_Facility(std::move(facility)) + : m_Severity(severity), m_Facility(std::move(facility)), m_IsNoOp(severity < Logger::GetMinLogSeverity()) { } /** @@ -210,6 +260,10 @@ Log::Log(LogSeverity severity, String facility) */ Log::~Log() { + if (m_IsNoOp) { + return; + } + LogEntry entry; entry.Timestamp = Utility::GetTime(); entry.Severity = m_Severity; @@ -264,6 +318,9 @@ Log::~Log() Log& Log::operator<<(const char *val) { - m_Buffer << val; + if (!m_IsNoOp) { + m_Buffer << val; + } + return *this; } diff --git a/lib/base/logger.hpp b/lib/base/logger.hpp index 6d87c29b7..10e0872ae 100644 --- a/lib/base/logger.hpp +++ b/lib/base/logger.hpp @@ -3,6 +3,7 @@ #ifndef LOGGER_H #define LOGGER_H +#include "base/atomic.hpp" #include "base/i2-base.hpp" #include "base/logger-ti.hpp" #include @@ -22,7 +23,10 @@ enum LogSeverity LogNotice, LogInformation, LogWarning, - LogCritical + LogCritical, + + // Just for internal comparision + LogNothing, }; /** @@ -76,6 +80,13 @@ public: static void SetConsoleLogSeverity(LogSeverity logSeverity); static LogSeverity GetConsoleLogSeverity(); + static inline + LogSeverity GetMinLogSeverity() + { + return m_MinLogSeverity.load(); + } + + void SetSeverity(const String& value, bool suppress_events = false, const Value& cookie = Empty) override; void ValidateSeverity(const Lazy& lvalue, const ValidationUtils& utils) final; protected: @@ -83,12 +94,16 @@ protected: void Stop(bool runtimeRemoved) override; private: + static void UpdateMinLogSeverity(); + static std::mutex m_Mutex; static std::set m_Loggers; static bool m_ConsoleLogEnabled; static std::atomic m_EarlyLoggingEnabled; static bool m_TimestampEnabled; static LogSeverity m_ConsoleLogSeverity; + static std::mutex m_UpdateMinLogSeverityMutex; + static Atomic m_MinLogSeverity; }; class Log @@ -116,6 +131,7 @@ private: LogSeverity m_Severity; String m_Facility; std::ostringstream m_Buffer; + bool m_IsNoOp; }; extern template Log& Log::operator<<(const Value&); diff --git a/lib/base/logger.ti b/lib/base/logger.ti index b9776c83d..44226cee4 100644 --- a/lib/base/logger.ti +++ b/lib/base/logger.ti @@ -9,7 +9,7 @@ namespace icinga abstract class Logger : ConfigObject { - [config] String severity { + [config, virtual] String severity { default {{{ return "information"; }}} }; };