diff --git a/src/common/Log.cpp b/src/common/Log.cpp index c7271df2c6..dca3bb04ab 100644 --- a/src/common/Log.cpp +++ b/src/common/Log.cpp @@ -30,33 +30,79 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Common.h" +#ifdef BUILD_ENGINE +// TODO: when cvar multiple registration is available, just declare the cvars in each module. +static Cvar::Cvar suppressionEnabled( + "logs.suppression.enabled", "Whether to suppress log messages that are printed too many times", Cvar::NONE, true); +static Cvar::Range> suppressionInterval( + "logs.suppression.interval", "Interval in milliseconds for detecting log spam", Cvar::NONE, 2000, 1, 1000000); +static Cvar::Range> suppressionCount( + "logs.suppression.count", "Number of occurrences for a message to be considered log spam", Cvar::NONE, 10, 1, 1000000); +static Cvar::Range> suppressionBufSize( + "logs.suppression.bufferSize", "How many distinct messages to track for log suppression", Cvar::NONE, 50, 1, 1000000); +static Cvar::Cvar logExtendAll( + "logs.writeSrcLocation.all", "Always print source code location for logs", Cvar::NONE, false); +static Cvar::Cvar logExtendWarn( + "logs.writeSrcLocation.warn", "Print source code location for Warn logs", Cvar::NONE, false); +static Cvar::Cvar logExtendNotice( + "logs.writeSrcLocation.notice", "Print source code location for Notice logs", Cvar::NONE, false); +static Cvar::Cvar logExtendVerbose( + "logs.writeSrcLocation.verbose", "Print source code location for Verbose logs", Cvar::NONE, false); +static Cvar::Cvar logExtendDebug( + "logs.writeSrcLocation.debug", "Print source code location for Debug logs", Cvar::NONE, false); + +#define GET_LOG_CVAR(type, name, object) (object.Get()) +#else +#define GET_LOG_CVAR(type, name, object) (GetCvarOrDie(name)) +template +static T GetCvarOrDie(Str::StringRef cvar) { + T value; + std::string valueString = Cvar::GetValue(cvar); + if (!Cvar::ParseCvarValue(valueString, value)) { + Sys::Error("Failed to deserialize cvar %s with value: %s", cvar, valueString); + } + return value; +} +#endif + namespace Log { - Cvar::Cvar logExtendAll( - "logs.writeSrcLocation.all", "Always print source code location for logs", Cvar::NONE, false ); - Cvar::Cvar logExtendWarn( - "logs.writeSrcLocation.warn", "Print source code location for Warn logs", Cvar::NONE, false ); - Cvar::Cvar logExtendNotice( - "logs.writeSrcLocation.notice", "Print source code location for Notice logs", Cvar::NONE, false ); - Cvar::Cvar logExtendVerbose( - "logs.writeSrcLocation.verbose", "Print source code location for Verbose logs", Cvar::NONE, false ); - Cvar::Cvar logExtendDebug( - "logs.writeSrcLocation.debug", "Print source code location for Debug logs", Cvar::NONE, false ); Logger::Logger(Str::StringRef name, std::string prefix, Level defaultLevel) : filterLevel(new Cvar::Cvar( "logs.level." + name, "Log::Level - logs from '" + name + "' below the level specified are filtered", 0, defaultLevel)), - prefix(prefix), enableSuppression(true) { + enableSuppression(true) + { + if (!prefix.empty()) { + // TODO allow prefixes without a space, e.g. a color code + this->prefix = prefix + " "; + } } - std::string Logger::Prefix(std::string message) const { - if (prefix.empty()) { - return message; - } else { - return prefix + " " + message; + std::string Logger::Prefix(Str::StringRef message) const { + return prefix + message; + } + + static bool WantLocationInfo(Log::Level level) { + if (GET_LOG_CVAR(bool, "logs.writeSrcLocation.all", logExtendAll)) { + return true; + } + switch (level) { + case Log::Level::DEBUG: + return GET_LOG_CVAR(bool, "logs.writeSrcLocation.debug", logExtendDebug); + case Log::Level::VERBOSE: + return GET_LOG_CVAR(bool, "logs.writeSrcLocation.verbose", logExtendVerbose); + case Log::Level::NOTICE: + return GET_LOG_CVAR(bool, "logs.writeSrcLocation.notice", logExtendNotice); + case Log::Level::WARNING: + return GET_LOG_CVAR(bool, "logs.writeSrcLocation.warn", logExtendWarn); } + ASSERT_UNREACHABLE(); } - void Logger::Dispatch(std::string message, Log::Level level, Str::StringRef format) { + void Logger::Dispatch(std::string message, Log::Level level, Str::StringRef format, const char* file, const char* function, int line) { + if (WantLocationInfo(level)) { + message = Str::Format("%s ^F(%s:%u, %s)", message, file, line, function); + } if (enableSuppression) { Log::DispatchWithSuppression(std::move(message), level, format); } else { @@ -136,15 +182,6 @@ namespace Log { } } - template - static T GetCvarOrDie(Str::StringRef cvar) { - T value; - std::string valueString = Cvar::GetValue(cvar); - if (!Cvar::ParseCvarValue(valueString, value)) { - Sys::Error("Failed to deserialize cvar %s with value: %s", cvar, valueString); - } - return value; - } namespace { // Log-spam suppression: if more than MAX_OCCURRENCES log messages with the same format string // are sent in less than INTERVAL_MS milliseconds, they will stop being printed. @@ -166,9 +203,9 @@ namespace Log { }; Result UpdateAndEvaluate(Str::StringRef messageFormat) { std::lock_guard lock(mutex); - int intervalMs = GetCvarOrDie("logs.suppression.interval"); - int maxOccurrences = GetCvarOrDie("logs.suppression.count"); - int bufferSize = GetCvarOrDie("logs.suppression.bufferSize"); + int intervalMs = GET_LOG_CVAR(int, "logs.suppression.interval", suppressionInterval); + int maxOccurrences = GET_LOG_CVAR(int, "logs.suppression.count", suppressionCount); + int bufferSize = GET_LOG_CVAR(int, "logs.suppression.bufferSize", suppressionBufSize); buf.resize(bufferSize); MessageStatistics* oldest = &buf[0]; int now = Sys::Milliseconds(); @@ -199,7 +236,7 @@ namespace Log { void DispatchWithSuppression(std::string message, Log::Level level, Str::StringRef format) { static LogSpamSuppressor suppressor; - if (level == Level::DEBUG || !GetCvarOrDie("logs.suppression.enabled")) { + if (level == Level::DEBUG || !GET_LOG_CVAR(bool, "logs.suppression.enabled", suppressionEnabled)) { DispatchByLevel(std::move(message), level); return; } diff --git a/src/common/Log.h b/src/common/Log.h index 5046d80923..dade1b62f8 100644 --- a/src/common/Log.h +++ b/src/common/Log.h @@ -51,12 +51,6 @@ namespace Log { // The default filtering level const Level DEFAULT_FILTER_LEVEL = Level::WARNING; - extern Cvar::Cvar logExtendAll; - extern Cvar::Cvar logExtendWarn; - extern Cvar::Cvar logExtendNotice; - extern Cvar::Cvar logExtendVerbose; - extern Cvar::Cvar logExtendDebug; - /* * Loggers are used to group logs by subsystems and allow logs * to be filtered by log level by subsystem. They are used like so @@ -116,9 +110,10 @@ namespace Log { Logger WithoutSuppression(); private: - void Dispatch(std::string message, Log::Level level, Str::StringRef format); + void Dispatch(std::string message, Log::Level level, Str::StringRef format, + const char* file, const char* function, int line); - std::string Prefix(std::string message) const; + std::string Prefix(Str::StringRef message) const; // the cvar logs.level. std::shared_ptr> filterLevel; @@ -131,22 +126,26 @@ namespace Log { /* * When debugging a function or before a logger is introduced for - * a module the following functions can be used for less typing. + * a module, the following signatures can be used for less typing. * However it shouldn't stay in production code because it * cannot be filtered and will clutter the console. + * + * These are not the real function declarations because macros are involved to get __LINE__ etc. */ +#if 0 template - void Warn( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ); + void Warn( Str::StringRef format, Args&& ... args ); template - void Notice( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ); + void Notice( Str::StringRef format, Args&& ... args ); template - void Verbose( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ); + void Verbose( Str::StringRef format, Args&& ... args ); template - void Debug( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ); + void Debug( Str::StringRef format, Args&& ... args ); +#endif /* * For messages which are not true log messages, but rather are produced by @@ -199,62 +198,35 @@ namespace Log { // Logger - inline std::string AddSrcLocation( const std::string& message, - const char* file, const char* function, const int line, - const bool extend ) { - if ( logExtendAll.Get() || extend ) { - return message + Str::Format( " ^F(%s:%u, %s)", - file, line, function ); - } - - return message; - } - template void Logger::WarnExt( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ) { if ( filterLevel->Get() <= Level::WARNING ) { - this->Dispatch( - AddSrcLocation( - Prefix( Str::Format( format, std::forward( args ) ... ) ), - file, function, line, logExtendWarn.Get() - ), - Level::WARNING, format ); + this->Dispatch(Prefix(Str::Format(format, std::forward(args)...)), + Level::WARNING, format, file, function, line); } } template void Logger::NoticeExt( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ) { if ( filterLevel->Get() <= Level::NOTICE ) { - this->Dispatch( - AddSrcLocation( - Prefix( Str::Format( format, std::forward( args ) ... ) ), - file, function, line, logExtendNotice.Get() - ), - Level::NOTICE, format ); + this->Dispatch(Prefix(Str::Format(format, std::forward(args)...)), + Level::NOTICE, format, file, function, line); } } template void Logger::VerboseExt( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ) { if ( filterLevel->Get() <= Level::VERBOSE ) { - this->Dispatch( - AddSrcLocation( - Prefix( Str::Format( format, std::forward( args ) ... ) ), - file, function, line, logExtendVerbose.Get() - ), - Level::VERBOSE, format ); + this->Dispatch(Prefix(Str::Format(format, std::forward(args)...)), + Level::VERBOSE, format, file, function, line); } } template void Logger::DebugExt( const char* file, const char* function, const int line, Str::StringRef format, Args&& ... args ) { if ( filterLevel->Get() <= Level::DEBUG ) { - this->Dispatch( - AddSrcLocation( - Prefix( Str::Format( format, std::forward( args ) ... ) ), - file, function, line, logExtendDebug.Get() - ), - Level::DEBUG, format ); + this->Dispatch(Prefix(Str::Format(format, std::forward(args)...)), + Level::DEBUG, format, file, function, line); } } diff --git a/src/engine/framework/LogSystem.cpp b/src/engine/framework/LogSystem.cpp index 1348189394..8c626c98ed 100644 --- a/src/engine/framework/LogSystem.cpp +++ b/src/engine/framework/LogSystem.cpp @@ -34,16 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LogSystem.h" namespace Log { - - static Cvar::Cvar suppressionEnabled( - "logs.suppression.enabled", "Whether to suppress log messages that are printed too many times", Cvar::NONE, true); - static Cvar::Range> suppressionInterval( - "logs.suppression.interval", "Interval in milliseconds for detecting log spam", Cvar::NONE, 2000, 1, 1000000); - static Cvar::Range> suppressionCount( - "logs.suppression.count", "Number of occurrences for a message to be considered log spam", Cvar::NONE, 10, 1, 1000000); - static Cvar::Range> suppressionBufSize( - "logs.suppression.bufferSize", "How many distinct messages to track for log suppression", Cvar::NONE, 50, 1, 1000000); - static Target* targets[MAX_TARGET_ID];