diff options
Diffstat (limited to 'src/zencore/logging.cpp')
| -rw-r--r-- | src/zencore/logging.cpp | 241 |
1 files changed, 216 insertions, 25 deletions
diff --git a/src/zencore/logging.cpp b/src/zencore/logging.cpp index c366df812..0d34372a9 100644 --- a/src/zencore/logging.cpp +++ b/src/zencore/logging.cpp @@ -7,39 +7,239 @@ #include <spdlog/sinks/null_sink.h> #include <spdlog/sinks/stdout_color_sinks.h> +#include <spdlog/spdlog.h> + +#if ZEN_PLATFORM_WINDOWS +# pragma section(".zlog$a", read) +# pragma section(".zlog$f", read) +# pragma section(".zlog$m", read) +# pragma section(".zlog$s", read) +# pragma section(".zlog$z", read) +#endif namespace zen { // We shadow the underlying spdlog default logger, in order to avoid a bunch of overhead -spdlog::logger* TheDefaultLogger; +LoggerRef TheDefaultLogger; } // namespace zen namespace zen::logging { -spdlog::logger& +using MemoryBuffer_t = fmt::basic_memory_buffer<char, 250>; + +struct LoggingContext +{ + inline LoggingContext(); + inline ~LoggingContext(); + + zen::logging::MemoryBuffer_t MessageBuffer; + + inline std::string_view Message() const { return std::string_view(MessageBuffer.data(), MessageBuffer.size()); } +}; + +LoggingContext::LoggingContext() +{ +} + +LoggingContext::~LoggingContext() +{ +} + +static inline bool +IsErrorLevel(int LogLevel) +{ + return (LogLevel == zen::logging::level::Err || LogLevel == zen::logging::level::Critical); +}; + +static_assert(sizeof(spdlog::source_loc) == sizeof(SourceLocation)); +static_assert(offsetof(spdlog::source_loc, filename) == offsetof(SourceLocation, filename)); +static_assert(offsetof(spdlog::source_loc, line) == offsetof(SourceLocation, line)); +static_assert(offsetof(spdlog::source_loc, funcname) == offsetof(SourceLocation, funcname)); + +void +EmitLogMessage(LoggerRef& Logger, int LogLevel, const std::string_view Message) +{ + const spdlog::level::level_enum InLevel = (spdlog::level::level_enum)LogLevel; + Logger.SpdLogger->log(InLevel, Message); + if (IsErrorLevel(LogLevel)) + { + if (LoggerRef ErrLogger = zen::logging::ErrorLog()) + { + ErrLogger.SpdLogger->log(InLevel, Message); + } + } +} + +void +EmitLogMessage(LoggerRef& Logger, int LogLevel, std::string_view Format, fmt::format_args Args) +{ + zen::logging::LoggingContext LogCtx; + fmt::vformat_to(fmt::appender(LogCtx.MessageBuffer), Format, Args); + zen::logging::EmitLogMessage(Logger, LogLevel, LogCtx.Message()); +} + +void +EmitLogMessage(LoggerRef& Logger, const SourceLocation& InLocation, int LogLevel, const std::string_view Message) +{ + const spdlog::source_loc& Location = *reinterpret_cast<const spdlog::source_loc*>(&InLocation); + const spdlog::level::level_enum InLevel = (spdlog::level::level_enum)LogLevel; + Logger.SpdLogger->log(Location, InLevel, Message); + if (IsErrorLevel(LogLevel)) + { + if (LoggerRef ErrLogger = zen::logging::ErrorLog()) + { + ErrLogger.SpdLogger->log(Location, InLevel, Message); + } + } +} + +void +EmitLogMessage(LoggerRef& Logger, const SourceLocation& InLocation, int LogLevel, std::string_view Format, fmt::format_args Args) +{ + zen::logging::LoggingContext LogCtx; + fmt::vformat_to(fmt::appender(LogCtx.MessageBuffer), Format, Args); + zen::logging::EmitLogMessage(Logger, InLocation, LogLevel, LogCtx.Message()); +} + +void +EmitConsoleLogMessage(int LogLevel, const std::string_view Message) +{ + const spdlog::level::level_enum InLevel = (spdlog::level::level_enum)LogLevel; + ConsoleLog().SpdLogger->log(InLevel, Message); +} + +void +EmitConsoleLogMessage(int LogLevel, std::string_view Format, fmt::format_args Args) +{ + zen::logging::LoggingContext LogCtx; + fmt::vformat_to(fmt::appender(LogCtx.MessageBuffer), Format, Args); + zen::logging::EmitConsoleLogMessage(LogLevel, LogCtx.Message()); +} + +} // namespace zen::logging + +namespace zen::logging::level { + +spdlog::level::level_enum +to_spdlog_level(LogLevel NewLogLevel) +{ + return static_cast<spdlog::level::level_enum>((int)NewLogLevel); +} + +LogLevel +to_logging_level(spdlog::level::level_enum NewLogLevel) +{ + return static_cast<LogLevel>((int)NewLogLevel); +} + +constinit std::string_view LevelNames[] = {ZEN_LEVEL_NAME_TRACE, + ZEN_LEVEL_NAME_DEBUG, + ZEN_LEVEL_NAME_INFO, + ZEN_LEVEL_NAME_WARNING, + ZEN_LEVEL_NAME_ERROR, + ZEN_LEVEL_NAME_CRITICAL, + ZEN_LEVEL_NAME_OFF}; + +level::LogLevel +ParseLogLevelString(std::string_view Name) +{ + for (int Level = 0; Level < level::LogLevelCount; ++Level) + { + if (LevelNames[Level] == Name) + return static_cast<level::LogLevel>(Level); + } + + if (Name == "warn") + { + return level::Warn; + } + + if (Name == "err") + { + return level::Err; + } + + return level::Off; +} + +std::string_view +ToStringView(level::LogLevel Level) +{ + if (int(Level) < level::LogLevelCount) + { + return LevelNames[int(Level)]; + } + + return "None"; +} + +} // namespace zen::logging::level + +namespace zen::logging { + +void +SetLogLevel(level::LogLevel NewLogLevel) +{ + spdlog::set_level(to_spdlog_level(NewLogLevel)); +} + +level::LogLevel +GetLogLevel() +{ + return level::to_logging_level(spdlog::get_level()); +} + +LoggerRef Default() { ZEN_ASSERT(TheDefaultLogger); - return *TheDefaultLogger; + return TheDefaultLogger; } void -SetDefault(std::shared_ptr<spdlog::logger> NewDefaultLogger) +SetDefault(std::string_view NewDefaultLoggerId) { + auto NewDefaultLogger = spdlog::get(std::string(NewDefaultLoggerId)); ZEN_ASSERT(NewDefaultLogger); + spdlog::set_default_logger(NewDefaultLogger); - TheDefaultLogger = spdlog::default_logger_raw(); + TheDefaultLogger = LoggerRef(*NewDefaultLogger); +} + +LoggerRef TheErrorLogger; + +LoggerRef +ErrorLog() +{ + return TheErrorLogger; } -spdlog::logger& +void +SetErrorLog(std::string_view NewErrorLoggerId) +{ + if (NewErrorLoggerId.empty()) + { + TheErrorLogger = {}; + } + else + { + auto NewErrorLogger = spdlog::get(std::string(NewErrorLoggerId)); + + ZEN_ASSERT(NewErrorLogger); + + TheErrorLogger = LoggerRef(*NewErrorLogger.get()); + } +} + +LoggerRef Get(std::string_view Name) { std::shared_ptr<spdlog::logger> Logger = spdlog::get(std::string(Name)); if (!Logger) { - Logger = Default().clone(std::string(Name)); + Logger = Default().SpdLogger->clone(std::string(Name)); spdlog::register_logger(Logger); } @@ -55,7 +255,7 @@ SuppressConsoleLog() ConLogger = spdlog::null_logger_mt("console"); } -spdlog::logger& +LoggerRef ConsoleLog() { std::call_once(ConsoleInitFlag, [&] { @@ -70,25 +270,10 @@ ConsoleLog() return *ConLogger; } -std::shared_ptr<spdlog::logger> TheErrorLogger; - -spdlog::logger* -ErrorLog() -{ - // This may return nullptr - return TheErrorLogger.get(); -} - -void -SetErrorLog(std::shared_ptr<spdlog::logger>&& NewErrorLogger) -{ - TheErrorLogger = std::move(NewErrorLogger); -} - void InitializeLogging() { - TheDefaultLogger = spdlog::default_logger_raw(); + TheDefaultLogger = *spdlog::default_logger_raw(); } void @@ -96,7 +281,7 @@ ShutdownLogging() { spdlog::drop_all(); spdlog::shutdown(); - TheDefaultLogger = nullptr; + TheDefaultLogger = {}; } bool @@ -130,6 +315,12 @@ EnableVTMode() namespace zen { +bool +LoggerRef::ShouldLog(int Level) const +{ + return SpdLogger->should_log(static_cast<spdlog::level::level_enum>(Level)); +} + thread_local ScopedActivityBase* t_ScopeStack = nullptr; ScopedActivityBase* |