diff --git a/include/logging.h b/include/logging.h index 79365f097..e613761a7 100644 --- a/include/logging.h +++ b/include/logging.h @@ -51,6 +51,12 @@ namespace Log /** A sensitive message that we should not store lightly. */ RAWIO = 4, + + /** The lowest log level supported. */ + LOWEST = CRITICAL, + + /** The highest log level supported. */ + HIGHEST = RAWIO, }; /** Converts a log level to a string. @@ -236,8 +242,11 @@ private: /** Whether we are currently logging to a file. */ bool logging = false; - /** Check whether raw logging is enabled. */ - void CheckRawLog(); + /** The highest level that loggers will accept. */ + Log::Level maxlevel = Level::HIGHEST; + + /** Check for the highest log level and warn about raw logging */ + void CheckLevel(); /** Writes a message to the server log. * @param level The level to log at. @@ -246,6 +255,15 @@ private: */ void Write(Level level, const std::string& type, const std::string& message); + template + void Write(Level level, const std::string& type, const char* format, Args&&... args) + { + if (maxlevel < level && !caching) + return; // No loggers care about this message. + + Write(level, type, fmt::vformat(format, fmt::make_format_args(args...))); + } + public: Manager(); @@ -283,7 +301,7 @@ public: template void Critical(const std::string& type, const char* format, Args&&... args) { - Write(Level::CRITICAL, type, fmt::vformat(format, fmt::make_format_args(args...))); + Write(Level::CRITICAL, type, format, std::forward(args)...); } /** Writes a warning message to the server log. @@ -303,7 +321,7 @@ public: template void Warning(const std::string& type, const char* format, Args&&... args) { - Write(Level::WARNING, type, fmt::vformat(format, fmt::make_format_args(args...))); + Write(Level::WARNING, type, format, std::forward(args)...); } /** Writes a normal message to the server log. @@ -323,7 +341,7 @@ public: template void Normal(const std::string& type, const char* format, Args&&... args) { - Write(Level::NORMAL, type, fmt::vformat(format, fmt::make_format_args(args...))); + Write(Level::NORMAL, type, format, std::forward(args)...); } /** Writes a debug message to the server log. @@ -342,7 +360,7 @@ public: template void Debug(const std::string& type, const char* format, Args&&... args) { - Write(Level::DEBUG, type, fmt::vformat(format, fmt::make_format_args(args...))); + Write(Level::DEBUG, type, format, std::forward(args)...); } /** Writes a raw I/O message to the server log. @@ -362,6 +380,6 @@ public: template void RawIO(const std::string& type, const char* format, Args&&... args) { - Write(Level::RAWIO, type, fmt::vformat(format, fmt::make_format_args(args...))); + Write(Level::RAWIO, type, format, std::forward(args)...); } }; diff --git a/src/logging.cpp b/src/logging.cpp index 665939f9b..ebae62019 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -224,7 +224,7 @@ void Log::Manager::OpenLogs(bool requiremethods) { const auto* option = ServerInstance->Config->CommandLine.forceprotodebug ? "--protocoldebug" : "--debug"; Normal("LOG", "Not opening loggers because we were started with {}", option); - CheckRawLog(); + CheckLevel(); return; } @@ -232,7 +232,7 @@ void Log::Manager::OpenLogs(bool requiremethods) if (!ServerInstance->Config->CommandLine.writelog) { Normal("LOG", "Not opening loggers because we were started with --nolog"); - CheckRawLog(); + CheckLevel(); return; } @@ -297,7 +297,7 @@ void Log::Manager::OpenLogs(bool requiremethods) cache.shrink_to_fit(); caching = false; } - CheckRawLog(); + CheckLevel(); } void Log::Manager::RegisterServices() @@ -316,12 +316,20 @@ void Log::Manager::UnloadEngine(const Engine* engine) Normal("LOG", "The {} log engine is unloading; removed {}/{} loggers.", engine->name.c_str(), logger_count - loggers.size(), logger_count); } -void Log::Manager::CheckRawLog() +void Log::Manager::CheckLevel() { // There might be a logger not from the config so we need to check this outside of the creation loop. - ServerInstance->Config->RawLog = std::any_of(loggers.begin(), loggers.end(), [](const auto& logger) { - return logger.level >= Level::RAWIO; - }); + auto newmaxlevel = Level::LOWEST; + for (const auto& logger : loggers) + { + if (logger.level > newmaxlevel) + newmaxlevel = logger.level; + } + + std::swap(maxlevel, newmaxlevel); + ServerInstance->Config->RawLog = (newmaxlevel >= Level::RAWIO); + + Debug("LOG", "Changed maximum log level from {} to {}", LevelToString(newmaxlevel), LevelToString(maxlevel)); } void Log::Manager::Write(Level level, const std::string& type, const std::string& message) @@ -329,6 +337,9 @@ void Log::Manager::Write(Level level, const std::string& type, const std::string if (logging) return; // Avoid log loops. + if (maxlevel < level && !caching) + return; // No loggers care about this message. + logging = true; time_t time = ServerInstance->Time(); for (auto& logger : loggers)