diff options
Diffstat (limited to 'src')
44 files changed, 820 insertions, 512 deletions
diff --git a/src/zen/cmds/copy_cmd.cpp b/src/zen/cmds/copy_cmd.cpp index 9f689e5bb..e5ddbfa85 100644 --- a/src/zen/cmds/copy_cmd.cpp +++ b/src/zen/cmds/copy_cmd.cpp @@ -122,7 +122,7 @@ CopyCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) { ++FailedFileCount; - ZEN_CONSOLE("Error: failed to copy '{}' to '{}': '{}'", FromPath, ToPath, Ex.what()); + ZEN_CONSOLE_ERROR("failed to copy '{}' to '{}': '{}'", FromPath, ToPath, Ex.what()); } } } @@ -154,7 +154,7 @@ CopyCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) if (Visitor.FailedFileCount) { - ZEN_CONSOLE("{} file copy operations FAILED"); + ZEN_CONSOLE_ERROR("{} file copy operations FAILED", Visitor.FailedFileCount); return 1; } @@ -182,7 +182,7 @@ CopyCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) } catch (std::exception& Ex) { - ZEN_CONSOLE("Error: failed to copy '{}' to '{}': '{}'", FromPath, ToPath, Ex.what()); + ZEN_CONSOLE_ERROR("Error: failed to copy '{}' to '{}': '{}'", FromPath, ToPath, Ex.what()); return 1; } diff --git a/src/zen/cmds/version_cmd.cpp b/src/zen/cmds/version_cmd.cpp index bd31862b4..41042533d 100644 --- a/src/zen/cmds/version_cmd.cpp +++ b/src/zen/cmds/version_cmd.cpp @@ -72,7 +72,7 @@ VersionCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) Version = Response.text; } - zen::ConsoleLog().info("{}", Version); + ZEN_CONSOLE("{}", Version); return 0; } diff --git a/src/zen/zen.cpp b/src/zen/zen.cpp index 241dbb599..65a02633a 100644 --- a/src/zen/zen.cpp +++ b/src/zen/zen.cpp @@ -37,6 +37,7 @@ ZEN_THIRD_PARTY_INCLUDES_START #include <cpr/cpr.h> #include <spdlog/sinks/ansicolor_sink.h> +#include <spdlog/spdlog.h> #include <gsl/gsl-lite.hpp> ZEN_THIRD_PARTY_INCLUDES_END @@ -181,8 +182,8 @@ main(int argc, char** argv) zen::logging::EnableVTMode(); std::set_terminate([]() { ZEN_CRITICAL("Program exited abnormally via std::terminate()"); }); - auto& DefaultLogger = zen::logging::Default(); - auto& Sinks = DefaultLogger.sinks(); + LoggerRef DefaultLogger = zen::logging::Default(); + auto& Sinks = DefaultLogger.SpdLogger->sinks(); Sinks.clear(); auto ConsoleSink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>(); @@ -411,11 +412,11 @@ main(int argc, char** argv) if (GlobalOptions.IsDebug) { - spdlog::set_level(spdlog::level::debug); + logging::SetLogLevel(logging::level::Debug); } if (GlobalOptions.IsVerbose) { - spdlog::set_level(spdlog::level::trace); + logging::SetLogLevel(logging::level::Trace); } for (const CommandInfo& CmdInfo : Commands) diff --git a/src/zencore/include/zencore/fmtutils.h b/src/zencore/include/zencore/fmtutils.h index 3d29625be..9c5bdae66 100644 --- a/src/zencore/include/zencore/fmtutils.h +++ b/src/zencore/include/zencore/fmtutils.h @@ -16,6 +16,26 @@ ZEN_THIRD_PARTY_INCLUDES_END // Custom formatting for some zencore types +template<typename T> +requires DerivedFrom<T, zen::StringBuilderBase> +struct fmt::formatter<T> : fmt::formatter<std::string_view> +{ + auto format(const zen::StringBuilderBase& a, format_context& ctx) const + { + return fmt::formatter<std::string_view>::format(a.ToView(), ctx); + } +}; + +template<typename T> +requires DerivedFrom<T, zen::NiceBase> +struct fmt::formatter<T> : fmt::formatter<std::string_view> +{ + auto format(const zen::NiceBase& a, format_context& ctx) const + { + return fmt::formatter<std::string_view>::format(std::string_view(a), ctx); + } +}; + template<> struct fmt::formatter<zen::IoHash> : formatter<string_view> { @@ -74,7 +94,8 @@ struct fmt::formatter<std::filesystem::path> : formatter<string_view> }; template<typename T> -struct fmt::formatter<T, std::enable_if_t<std::is_base_of<zen::PathBuilderBase, T>::value, char>> : fmt::formatter<std::string_view> +requires DerivedFrom<T, zen::PathBuilderBase> +struct fmt::formatter<T> : fmt::formatter<std::string_view> { auto format(const zen::PathBuilderBase& a, format_context& ctx) const { diff --git a/src/zencore/include/zencore/logbase.h b/src/zencore/include/zencore/logbase.h new file mode 100644 index 000000000..ad873aa51 --- /dev/null +++ b/src/zencore/include/zencore/logbase.h @@ -0,0 +1,96 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <string_view> + +#define ZEN_LOG_LEVEL_TRACE 0 +#define ZEN_LOG_LEVEL_DEBUG 1 +#define ZEN_LOG_LEVEL_INFO 2 +#define ZEN_LOG_LEVEL_WARN 3 +#define ZEN_LOG_LEVEL_ERROR 4 +#define ZEN_LOG_LEVEL_CRITICAL 5 +#define ZEN_LOG_LEVEL_OFF 6 + +#define ZEN_LEVEL_NAME_TRACE std::string_view("trace", 5) +#define ZEN_LEVEL_NAME_DEBUG std::string_view("debug", 5) +#define ZEN_LEVEL_NAME_INFO std::string_view("info", 4) +#define ZEN_LEVEL_NAME_WARNING std::string_view("warning", 7) +#define ZEN_LEVEL_NAME_ERROR std::string_view("error", 5) +#define ZEN_LEVEL_NAME_CRITICAL std::string_view("critical", 8) +#define ZEN_LEVEL_NAME_OFF std::string_view("off", 3) + +namespace zen::logging::level { + +enum LogLevel : int +{ + Trace = ZEN_LOG_LEVEL_TRACE, + Debug = ZEN_LOG_LEVEL_DEBUG, + Info = ZEN_LOG_LEVEL_INFO, + Warn = ZEN_LOG_LEVEL_WARN, + Err = ZEN_LOG_LEVEL_ERROR, + Critical = ZEN_LOG_LEVEL_CRITICAL, + Off = ZEN_LOG_LEVEL_OFF, + LogLevelCount +}; + +LogLevel ParseLogLevelString(std::string_view String); +std::string_view ToStringView(LogLevel Level); + +} // namespace zen::logging::level + +namespace zen::logging { + +void SetLogLevel(level::LogLevel NewLogLevel); +level::LogLevel GetLogLevel(); + +} // namespace zen::logging + +namespace spdlog { +class logger; +} + +namespace zen::logging { + +struct SourceLocation +{ + constexpr SourceLocation() = default; + constexpr SourceLocation(const char* filename_in, int line_in, const char* funcname_in) + : filename(filename_in) + , line(line_in) + , funcname(funcname_in) + { + } + + constexpr bool empty() const noexcept { return line == 0; } + + // IMPORTANT NOTE: the layout of this class must match the spdlog::source_loc class + // since we currently pass a pointer to it into spdlog after casting it to + // spdlog::source_loc* + // + // This is intended to be an intermediate state, before we (probably) transition off + // spdlog entirely + + const char* filename{nullptr}; + int line{0}; + const char* funcname{nullptr}; +}; + +} // namespace zen::logging + +namespace zen { + +struct LoggerRef +{ + LoggerRef() = default; + LoggerRef(spdlog::logger& InLogger) : SpdLogger(&InLogger) {} + + LoggerRef Logger() { return *this; } + + bool ShouldLog(int Level) const; + inline operator bool() const { return SpdLogger != nullptr; } + + spdlog::logger* SpdLogger = nullptr; +}; + +} // namespace zen diff --git a/src/zencore/include/zencore/logging.h b/src/zencore/include/zencore/logging.h index c0d966475..e3eb524e9 100644 --- a/src/zencore/include/zencore/logging.h +++ b/src/zencore/include/zencore/logging.h @@ -2,138 +2,179 @@ #pragma once +#include <zencore/logbase.h> #include <zencore/zencore.h> -ZEN_THIRD_PARTY_INCLUDES_START -#include <spdlog/spdlog.h> -#undef GetObject -ZEN_THIRD_PARTY_INCLUDES_END - -#include <string_view> +#include <fmt/args.h> + +#if ZEN_PLATFORM_WINDOWS +# define ZEN_LOG_SECTION(Id) ZEN_DATA_SECTION(Id) +# pragma section(".zlog$f", read) +# pragma section(".zlog$l", read) +# pragma section(".zlog$m", read) +# pragma section(".zlog$s", read) +# define ZEN_DECLARE_FUNCTION static constinit ZEN_LOG_SECTION(".zlog$f") char FuncName[] = __FUNCTION__; +# define ZEN_LOG_FUNCNAME FuncName +#else +# define ZEN_LOG_SECTION(Id) +# define ZEN_DECLARE_FUNCTION +# define ZEN_LOG_FUNCNAME static_cast<const char*>(__func__) +#endif namespace zen::logging { -spdlog::logger& Default(); -void SetDefault(std::shared_ptr<spdlog::logger> NewDefaultLogger); -spdlog::logger& ConsoleLog(); -void SuppressConsoleLog(); -spdlog::logger& Get(std::string_view Name); -spdlog::logger* ErrorLog(); -void SetErrorLog(std::shared_ptr<spdlog::logger>&& NewErrorLogger); - void InitializeLogging(); void ShutdownLogging(); - bool EnableVTMode(); +LoggerRef Default(); +void SetDefault(std::string_view NewDefaultLoggerId); +LoggerRef ConsoleLog(); +void SuppressConsoleLog(); +LoggerRef ErrorLog(); +void SetErrorLog(std::string_view LoggerId); +LoggerRef Get(std::string_view Name); + +struct LogCategory +{ + inline LogCategory(std::string_view InCategory) : CategoryName(InCategory) {} + + inline zen::LoggerRef Logger() + { + if (LoggerRef) + { + return LoggerRef; + } + + LoggerRef = zen::logging::Get(CategoryName); + return LoggerRef; + } + + std::string CategoryName; + zen::LoggerRef LoggerRef; +}; + +void EmitConsoleLogMessage(int LogLevel, std::string_view Message); +void EmitConsoleLogMessage(int LogLevel, std::string_view Format, fmt::format_args Args); +void EmitLogMessage(LoggerRef& Logger, int LogLevel, std::string_view Message); +void EmitLogMessage(LoggerRef& Logger, const SourceLocation& Location, int LogLevel, std::string_view Message); +void EmitLogMessage(LoggerRef& Logger, int LogLevel, std::string_view Format, fmt::format_args Args); +void EmitLogMessage(LoggerRef& Logger, const SourceLocation& Location, int LogLevel, std::string_view Format, fmt::format_args Args); + } // namespace zen::logging namespace zen { -extern spdlog::logger* TheDefaultLogger; -inline spdlog::logger& +extern LoggerRef TheDefaultLogger; + +inline LoggerRef Log() { - if (TheDefaultLogger == nullptr) + if (TheDefaultLogger) { - return zen::logging::ConsoleLog(); + return TheDefaultLogger; } - return *TheDefaultLogger; + return zen::logging::ConsoleLog(); } using logging::ConsoleLog; using logging::ErrorLog; + } // namespace zen using zen::ConsoleLog; using zen::ErrorLog; using zen::Log; -struct LogCategory -{ - LogCategory(std::string_view InCategory) : Category(InCategory) {} - - spdlog::logger& Logger() - { - static spdlog::logger& Inst = zen::logging::Get(Category); - return Inst; - } - - std::string Category; -}; - inline consteval bool -LogIsErrorLevel(int level) +LogIsErrorLevel(int LogLevel) { - return (level == spdlog::level::err || level == spdlog::level::critical); + return (LogLevel == zen::logging::level::Err || LogLevel == zen::logging::level::Critical); }; -#define ZEN_LOG_WITH_LOCATION(logger, loc, level, fmtstr, ...) \ - do \ - { \ - using namespace std::literals; \ - if (logger.should_log(level)) \ - { \ - logger.log(loc, level, fmtstr, ##__VA_ARGS__); \ - if (LogIsErrorLevel(level)) \ - { \ - if (auto ErrLogger = zen::logging::ErrorLog(); ErrLogger != nullptr) \ - { \ - ErrLogger->log(loc, level, fmtstr, ##__VA_ARGS__); \ - } \ - } \ - } \ +#if ZEN_BUILD_DEBUG +# define ZEN_CHECK_FORMAT_STRING(fmtstr, ...) \ + while (false) \ + { \ + (void)fmt::format(fmtstr, ##__VA_ARGS__); \ + } +#else +# define ZEN_CHECK_FORMAT_STRING(fmtstr, ...) \ + while (false) \ + { \ + } +#endif + +#define ZEN_LOG_WITH_LOCATION(InLogger, InLevel, fmtstr, ...) \ + do \ + { \ + using namespace std::literals; \ + ZEN_DECLARE_FUNCTION \ + static constinit ZEN_LOG_SECTION(".zlog$s") char FileName[] = __FILE__; \ + static constinit ZEN_LOG_SECTION(".zlog$m") char FormatString[] = fmtstr; \ + static constinit ZEN_LOG_SECTION(".zlog$l") zen::logging::SourceLocation Location{FileName, __LINE__, ZEN_LOG_FUNCNAME}; \ + zen::LoggerRef Logger = InLogger; \ + ZEN_CHECK_FORMAT_STRING(fmtstr##sv, ##__VA_ARGS__); \ + if (Logger.ShouldLog(InLevel)) \ + { \ + zen::logging::EmitLogMessage(Logger, \ + Location, \ + InLevel, \ + std::string_view(FormatString, sizeof FormatString - 1), \ + fmt::make_format_args(__VA_ARGS__)); \ + } \ } while (false); -#define ZEN_LOG(logger, level, fmtstr, ...) ZEN_LOG_WITH_LOCATION(logger, spdlog::source_loc{}, level, fmtstr, ##__VA_ARGS__) - -#define ZEN_DEFINE_LOG_CATEGORY_STATIC(Category, Name) \ - static struct LogCategory##Category : public LogCategory \ - { \ - LogCategory##Category() : LogCategory(Name) {} \ - } Category; - -#define ZEN_LOG_TRACE(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), spdlog::level::trace, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_LOG_DEBUG(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), spdlog::level::debug, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_LOG_INFO(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), spdlog::level::info, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_LOG_WARN(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), spdlog::level::warn, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_LOG_ERROR(Category, fmtstr, ...) \ - ZEN_LOG_WITH_LOCATION(Category.Logger(), \ - spdlog::source_loc(__FILE__, __LINE__, SPDLOG_FUNCTION), \ - spdlog::level::err, \ - fmtstr##sv, \ - ##__VA_ARGS__) - -#define ZEN_LOG_CRITICAL(Category, fmtstr, ...) \ - ZEN_LOG_WITH_LOCATION(Category.Logger(), \ - spdlog::source_loc(__FILE__, __LINE__, SPDLOG_FUNCTION), \ - spdlog::level::critical, \ - fmtstr##sv, \ - ##__VA_ARGS__) - - // Helper macros for logging - -#define ZEN_TRACE(fmtstr, ...) ZEN_LOG(Log(), spdlog::level::trace, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_DEBUG(fmtstr, ...) ZEN_LOG(Log(), spdlog::level::debug, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_INFO(fmtstr, ...) ZEN_LOG(Log(), spdlog::level::info, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_WARN(fmtstr, ...) ZEN_LOG(Log(), spdlog::level::warn, fmtstr##sv, ##__VA_ARGS__) -#define ZEN_ERROR(fmtstr, ...) \ - ZEN_LOG_WITH_LOCATION(Log(), spdlog::source_loc(__FILE__, __LINE__, SPDLOG_FUNCTION), spdlog::level::err, fmtstr##sv, ##__VA_ARGS__) - -#define ZEN_CRITICAL(fmtstr, ...) \ - ZEN_LOG_WITH_LOCATION(Log(), \ - spdlog::source_loc(__FILE__, __LINE__, SPDLOG_FUNCTION), \ - spdlog::level::critical, \ - fmtstr##sv, \ - ##__VA_ARGS__) - -#define ZEN_CONSOLE(fmtstr, ...) \ - do \ - { \ - using namespace std::literals; \ - ConsoleLog().info(fmtstr##sv, ##__VA_ARGS__); \ +#define ZEN_LOG(InLogger, InLevel, fmtstr, ...) \ + do \ + { \ + using namespace std::literals; \ + static constinit ZEN_LOG_SECTION(".zlog$m") char FormatString[] = fmtstr; \ + zen::LoggerRef Logger = InLogger; \ + ZEN_CHECK_FORMAT_STRING(fmtstr##sv, ##__VA_ARGS__); \ + if (Logger.ShouldLog(InLevel)) \ + { \ + zen::logging::EmitLogMessage(Logger, \ + InLevel, \ + std::string_view(FormatString, sizeof FormatString - 1), \ + fmt::make_format_args(__VA_ARGS__)); \ + } \ + } while (false); + +#define ZEN_DEFINE_LOG_CATEGORY_STATIC(Category, Name) \ + static zen::logging::LogCategory Category { Name } + +#define ZEN_LOG_TRACE(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), zen::logging::level::Trace, fmtstr, ##__VA_ARGS__) +#define ZEN_LOG_DEBUG(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), zen::logging::level::Debug, fmtstr, ##__VA_ARGS__) +#define ZEN_LOG_INFO(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), zen::logging::level::Info, fmtstr, ##__VA_ARGS__) +#define ZEN_LOG_WARN(Category, fmtstr, ...) ZEN_LOG(Category.Logger(), zen::logging::level::Warn, fmtstr, ##__VA_ARGS__) +#define ZEN_LOG_ERROR(Category, fmtstr, ...) ZEN_LOG_WITH_LOCATION(Category.Logger(), zen::logging::level::Err, fmtstr, ##__VA_ARGS__) +#define ZEN_LOG_CRITICAL(Category, fmtstr, ...) \ + ZEN_LOG_WITH_LOCATION(Category.Logger(), zen::logging::level::Critical, fmtstr, ##__VA_ARGS__) + +#define ZEN_TRACE(fmtstr, ...) ZEN_LOG(Log(), zen::logging::level::Trace, fmtstr, ##__VA_ARGS__) +#define ZEN_DEBUG(fmtstr, ...) ZEN_LOG(Log(), zen::logging::level::Debug, fmtstr, ##__VA_ARGS__) +#define ZEN_INFO(fmtstr, ...) ZEN_LOG(Log(), zen::logging::level::Info, fmtstr, ##__VA_ARGS__) +#define ZEN_WARN(fmtstr, ...) ZEN_LOG(Log(), zen::logging::level::Warn, fmtstr, ##__VA_ARGS__) +#define ZEN_ERROR(fmtstr, ...) ZEN_LOG_WITH_LOCATION(Log(), zen::logging::level::Err, fmtstr, ##__VA_ARGS__) +#define ZEN_CRITICAL(fmtstr, ...) ZEN_LOG_WITH_LOCATION(Log(), zen::logging::level::Critical, fmtstr, ##__VA_ARGS__) + +#define ZEN_CONSOLE_LOG(InLevel, fmtstr, ...) \ + do \ + { \ + using namespace std::literals; \ + ZEN_CHECK_FORMAT_STRING(fmtstr##sv, ##__VA_ARGS__); \ + zen::logging::EmitConsoleLogMessage(InLevel, fmtstr, fmt::make_format_args(__VA_ARGS__)); \ } while (false) +#define ZEN_CONSOLE(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Info, fmtstr, ##__VA_ARGS__) +#define ZEN_CONSOLE_TRACE(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Trace, fmtstr, ##__VA_ARGS__) +#define ZEN_CONSOLE_DEBUG(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Debug, fmtstr, ##__VA_ARGS__) +#define ZEN_CONSOLE_INFO(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Info, fmtstr, ##__VA_ARGS__) +#define ZEN_CONSOLE_WARN(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Warn, fmtstr, ##__VA_ARGS__) +#define ZEN_CONSOLE_ERROR(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Err, fmtstr, ##__VA_ARGS__) +#define ZEN_CONSOLE_CRITICAL(fmtstr, ...) ZEN_CONSOLE_LOG(zen::logging::level::Critical, fmtstr, ##__VA_ARGS__) + ////////////////////////////////////////////////////////////////////////// namespace zen { @@ -187,30 +228,20 @@ std::string_view EmitActivitiesForLogging(StringBuilderBase& OutString); #define ZEN_LOG_SCOPE(...) ScopedLazyActivity $Activity##__LINE__([&](StringBuilderBase& Out) { Out << fmt::format(__VA_ARGS__); }) -#define ZEN_SCOPED_ERROR(fmtstr, ...) \ - do \ - { \ - ExtendableStringBuilder<256> ScopeString; \ - const std::string_view Scopes = EmitActivitiesForLogging(ScopeString); \ - ZEN_LOG_WITH_LOCATION(Log(), \ - spdlog::source_loc(__FILE__, __LINE__, SPDLOG_FUNCTION), \ - spdlog::level::err, \ - fmtstr "{}"sv, \ - ##__VA_ARGS__, \ - Scopes); \ +#define ZEN_SCOPED_ERROR(fmtstr, ...) \ + do \ + { \ + ExtendableStringBuilder<256> ScopeString; \ + const std::string_view Scopes = EmitActivitiesForLogging(ScopeString); \ + ZEN_LOG_WITH_LOCATION(Log(), zen::logging::level::Err, fmtstr "{}", ##__VA_ARGS__, Scopes); \ } while (false) -#define ZEN_SCOPED_CRITICAL(fmtstr, ...) \ - do \ - { \ - ExtendableStringBuilder<256> ScopeString; \ - const std::string_view Scopes = EmitActivitiesForLogging(ScopeString); \ - ZEN_LOG_WITH_LOCATION(Log(), \ - spdlog::source_loc(__FILE__, __LINE__, SPDLOG_FUNCTION), \ - spdlog::level::critical, \ - fmtstr "{}"sv, \ - ##__VA_ARGS__, \ - Scopes); \ +#define ZEN_SCOPED_CRITICAL(fmtstr, ...) \ + do \ + { \ + ExtendableStringBuilder<256> ScopeString; \ + const std::string_view Scopes = EmitActivitiesForLogging(ScopeString); \ + ZEN_LOG_WITH_LOCATION(Log(), zen::logging::level::Critical, fmtstr "{}", ##__VA_ARGS__, Scopes); \ } while (false) ScopedActivityBase* GetThreadActivity(); diff --git a/src/zencore/include/zencore/string.h b/src/zencore/include/zencore/string.h index d0bd38acc..e3de2224c 100644 --- a/src/zencore/include/zencore/string.h +++ b/src/zencore/include/zencore/string.h @@ -17,10 +17,6 @@ #include <type_traits> -ZEN_THIRD_PARTY_INCLUDES_START -#include <fmt/format.h> -ZEN_THIRD_PARTY_INCLUDES_END - namespace zen { ////////////////////////////////////////////////////////////////////////// @@ -1141,21 +1137,3 @@ private: void string_forcelink(); // internal } // namespace zen - -template<typename T> -struct fmt::formatter<T, std::enable_if_t<std::is_base_of<zen::StringBuilderBase, T>::value, char>> : fmt::formatter<std::string_view> -{ - auto format(const zen::StringBuilderBase& a, format_context& ctx) const - { - return fmt::formatter<std::string_view>::format(a.ToView(), ctx); - } -}; - -template<typename T> -struct fmt::formatter<T, std::enable_if_t<std::is_base_of<zen::NiceBase, T>::value, char>> : fmt::formatter<std::string_view> -{ - auto format(const zen::NiceBase& a, format_context& ctx) const - { - return fmt::formatter<std::string_view>::format(std::string_view(a), ctx); - } -}; diff --git a/src/zencore/include/zencore/zencore.h b/src/zencore/include/zencore/zencore.h index 299fa2c31..562376c95 100644 --- a/src/zencore/include/zencore/zencore.h +++ b/src/zencore/include/zencore/zencore.h @@ -229,10 +229,12 @@ static_assert(sizeof(wchar_t) == 2, "wchar_t is expected to be two bytes in size #if ZEN_PLATFORM_WINDOWS // Tells the compiler to put the decorated function in a certain section (aka. segment) of the executable. # define ZEN_CODE_SECTION(Name) __declspec(code_seg(Name)) +# define ZEN_DATA_SECTION(Name) __declspec(allocate(Name)) # define ZEN_FORCENOINLINE __declspec(noinline) /* Force code to NOT be inline */ # define LINE_TERMINATOR_ANSI "\r\n" #else # define ZEN_CODE_SECTION(Name) +# define ZEN_DATA_SECTION(Name) # define ZEN_FORCENOINLINE # define LINE_TERMINATOR_ANSI "\n" #endif 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* diff --git a/src/zencore/testing.cpp b/src/zencore/testing.cpp index 6e1f55eda..54d89ded2 100644 --- a/src/zencore/testing.cpp +++ b/src/zencore/testing.cpp @@ -32,11 +32,11 @@ TestRunner::ApplyCommandLine(int argc, char const* const* argv) { if (argv[i] == "--debug"sv) { - spdlog::set_level(spdlog::level::debug); + zen::logging::SetLogLevel(zen::logging::level::Debug); } else if (argv[i] == "--verbose"sv) { - spdlog::set_level(spdlog::level::trace); + zen::logging::SetLogLevel(zen::logging::level::Trace); } } diff --git a/src/zenhttp/auth/authmgr.cpp b/src/zenhttp/auth/authmgr.cpp index f75e4edb2..e84f63a3f 100644 --- a/src/zenhttp/auth/authmgr.cpp +++ b/src/zenhttp/auth/authmgr.cpp @@ -493,10 +493,10 @@ private: using OpenIdProviderMap = std::unordered_map<std::string, std::unique_ptr<OpenIdProvider>>; using OpenIdTokenMap = std::unordered_map<std::string, OpenIdToken>; - spdlog::logger& Log() { return m_Log; } + LoggerRef Log() { return m_Log; } AuthConfig m_Config; - spdlog::logger& m_Log; + LoggerRef m_Log; BackgroundThread m_BackgroundThread; OpenIdProviderMap m_OpenIdProviders; OpenIdTokenMap m_OpenIdTokens; diff --git a/src/zenhttp/httpclient.cpp b/src/zenhttp/httpclient.cpp index caefce5f4..1299d51c1 100644 --- a/src/zenhttp/httpclient.cpp +++ b/src/zenhttp/httpclient.cpp @@ -22,6 +22,12 @@ ZEN_THIRD_PARTY_INCLUDES_START #include <cpr/cpr.h> ZEN_THIRD_PARTY_INCLUDES_END +#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC +# include <fcntl.h> +# include <sys/stat.h> +# include <unistd.h> +#endif + static std::atomic<uint32_t> HttpClientRequestIdCounter{0}; namespace zen { @@ -121,7 +127,7 @@ CommonResponse(cpr::Response&& HttpResponse, IoBuffer&& Payload = {}) struct HttpClient::Impl : public RefCounted { - Impl(spdlog::logger& Log); + Impl(LoggerRef Log); ~Impl(); // Session allocation @@ -169,7 +175,7 @@ struct HttpClient::Impl : public RefCounted return Result; } - spdlog::logger& Logger() { return Outer->Logger(); } + LoggerRef Logger() { return Outer->Logger(); } private: Impl* Outer; @@ -185,17 +191,17 @@ struct HttpClient::Impl : public RefCounted const KeyValueMap& AdditionalHeader, const KeyValueMap& Parameters); - spdlog::logger& Logger() { return m_Log; } + LoggerRef Logger() { return m_Log; } private: - spdlog::logger& m_Log; + LoggerRef m_Log; RwLock m_SessionLock; std::vector<cpr::Session*> m_Sessions; void ReleaseSession(cpr::Session*); }; -HttpClient::Impl::Impl(spdlog::logger& Log) : m_Log(Log) +HttpClient::Impl::Impl(LoggerRef Log) : m_Log(Log) { } diff --git a/src/zenhttp/include/zenhttp/httpclient.h b/src/zenhttp/include/zenhttp/httpclient.h index ae1e2bf20..9de5c7cce 100644 --- a/src/zenhttp/include/zenhttp/httpclient.h +++ b/src/zenhttp/include/zenhttp/httpclient.h @@ -5,16 +5,13 @@ #include "zenhttp.h" #include <zencore/iobuffer.h> +#include <zencore/logbase.h> #include <zencore/uid.h> #include <zenhttp/httpcommon.h> #include <optional> #include <unordered_map> -namespace spdlog { -class logger; -} // namespace spdlog - namespace zen { class CbPackage; @@ -148,13 +145,13 @@ public: return std::make_pair("Accept", MapContentTypeToString(ContentType)); } - spdlog::logger& Logger() { return m_Log; } + LoggerRef Logger() { return m_Log; } std::string_view GetBaseUri() const { return m_BaseUri; } private: struct Impl; - spdlog::logger& m_Log; + LoggerRef m_Log; std::string m_BaseUri; std::string m_SessionId; const HttpClientSettings m_ConnectionSettings; diff --git a/src/zenhttp/include/zenhttp/httpstats.h b/src/zenhttp/include/zenhttp/httpstats.h index 4a1cdcb20..e6fea6765 100644 --- a/src/zenhttp/include/zenhttp/httpstats.h +++ b/src/zenhttp/include/zenhttp/httpstats.h @@ -21,13 +21,13 @@ public: virtual void UnregisterHandler(std::string_view Id, IHttpStatsProvider& Provider) override; private: - spdlog::logger& m_Log; + LoggerRef m_Log; HttpRequestRouter m_Router; - inline spdlog::logger& Log() { return m_Log; } + inline LoggerRef Log() { return m_Log; } RwLock m_Lock; std::map<std::string, IHttpStatsProvider*> m_Providers; }; -} // namespace zen
\ No newline at end of file +} // namespace zen diff --git a/src/zenhttp/include/zenhttp/httpstatus.h b/src/zenhttp/include/zenhttp/httpstatus.h index b04e45324..093f62481 100644 --- a/src/zenhttp/include/zenhttp/httpstatus.h +++ b/src/zenhttp/include/zenhttp/httpstatus.h @@ -26,13 +26,13 @@ public: void UnregisterHandler(std::string_view Id, IHttpStatusProvider& Provider); private: - spdlog::logger& m_Log; + LoggerRef m_Log; HttpRequestRouter m_Router; RwLock m_Lock; std::map<std::string, IHttpStatusProvider*> m_Providers; - inline spdlog::logger& Log() { return m_Log; } + inline LoggerRef Log() { return m_Log; } }; -} // namespace zen
\ No newline at end of file +} // namespace zen diff --git a/src/zenhttp/servers/httpasio.cpp b/src/zenhttp/servers/httpasio.cpp index 0c6b189f9..44398d92d 100644 --- a/src/zenhttp/servers/httpasio.cpp +++ b/src/zenhttp/servers/httpasio.cpp @@ -47,18 +47,18 @@ static constinit uint32_t HashSession = HashStringAsLowerDjb2("UE-Session"sv); static constinit uint32_t HashRequest = HashStringAsLowerDjb2("UE-Request"sv); static constinit uint32_t HashRange = HashStringAsLowerDjb2("Range"sv); -inline spdlog::logger& +inline LoggerRef InitLogger() { - spdlog::logger& Logger = logging::Get("asio"); + LoggerRef Logger = logging::Get("asio"); // Logger.set_level(spdlog::level::trace); return Logger; } -inline spdlog::logger& +inline LoggerRef Log() { - static spdlog::logger& g_Logger = InitLogger(); + static LoggerRef g_Logger = InitLogger(); return g_Logger; } @@ -1007,7 +1007,7 @@ HttpAsioServer::Run(bool IsInteractive) #if ZEN_PLATFORM_WINDOWS if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (asio HTTP). Press ESC or Q to quit"); + ZEN_CONSOLE("Zen Server running (asio HTTP). Press ESC or Q to quit"); } do @@ -1027,7 +1027,7 @@ HttpAsioServer::Run(bool IsInteractive) #else if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (asio HTTP). Ctrl-C to quit"); + ZEN_CONSOLE("Zen Server running (asio HTTP). Ctrl-C to quit"); } do diff --git a/src/zenhttp/servers/httpmulti.cpp b/src/zenhttp/servers/httpmulti.cpp index 6b7060d5e..d8ebdc9c0 100644 --- a/src/zenhttp/servers/httpmulti.cpp +++ b/src/zenhttp/servers/httpmulti.cpp @@ -63,7 +63,7 @@ HttpMultiServer::Run(bool IsInteractiveSession) #if ZEN_PLATFORM_WINDOWS if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (multi server). Press ESC or Q to quit"); + ZEN_CONSOLE("Zen Server running (multi server). Press ESC or Q to quit"); } do @@ -83,7 +83,7 @@ HttpMultiServer::Run(bool IsInteractiveSession) #else if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (null HTTP). Ctrl-C to quit"); + ZEN_CONSOLE("Zen Server running (null HTTP). Ctrl-C to quit"); } do diff --git a/src/zenhttp/servers/httpnull.cpp b/src/zenhttp/servers/httpnull.cpp index 658f51831..7d3e9079a 100644 --- a/src/zenhttp/servers/httpnull.cpp +++ b/src/zenhttp/servers/httpnull.cpp @@ -44,7 +44,7 @@ HttpNullServer::Run(bool IsInteractiveSession) #if ZEN_PLATFORM_WINDOWS if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (null HTTP). Press ESC or Q to quit"); + ZEN_CONSOLE("Zen Server running (null HTTP). Press ESC or Q to quit"); } do @@ -64,7 +64,7 @@ HttpNullServer::Run(bool IsInteractiveSession) #else if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (null HTTP). Ctrl-C to quit"); + ZEN_CONSOLE("Zen Server running (null HTTP). Ctrl-C to quit"); } do diff --git a/src/zenhttp/servers/httpplugin.cpp b/src/zenhttp/servers/httpplugin.cpp index 3c727763b..4ae7cd87a 100644 --- a/src/zenhttp/servers/httpplugin.cpp +++ b/src/zenhttp/servers/httpplugin.cpp @@ -651,7 +651,7 @@ HttpPluginServerImpl::Run(bool IsInteractive) # if ZEN_PLATFORM_WINDOWS if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (plugin HTTP). Press ESC or Q to quit"); + ZEN_CONSOLE("Zen Server running (plugin HTTP). Press ESC or Q to quit"); } do @@ -671,7 +671,7 @@ HttpPluginServerImpl::Run(bool IsInteractive) # else if (TestMode == false) { - zen::logging::ConsoleLog().info("Zen Server running (plugin HTTP). Ctrl-C to quit"); + ZEN_CONSOLE("Zen Server running (plugin HTTP). Ctrl-C to quit"); } do diff --git a/src/zenhttp/servers/httpsys.cpp b/src/zenhttp/servers/httpsys.cpp index f1cd3e3fc..4eeab6662 100644 --- a/src/zenhttp/servers/httpsys.cpp +++ b/src/zenhttp/servers/httpsys.cpp @@ -23,10 +23,6 @@ # include <http.h> -namespace spdlog { -class logger; -} - namespace zen { /** @@ -70,9 +66,9 @@ private: void UnregisterService(const char* Endpoint, HttpService& Service); private: - spdlog::logger& m_Log; - spdlog::logger& m_RequestLog; - spdlog::logger& Log() { return m_Log; } + LoggerRef m_Log; + LoggerRef m_RequestLog; + LoggerRef Log() { return m_Log; } bool m_IsOk = false; bool m_IsHttpInitialized = false; @@ -1239,7 +1235,7 @@ HttpSysServer::Run(bool IsInteractive) { if (IsInteractive) { - zen::logging::ConsoleLog().info("Zen Server running (http.sys). Press ESC or Q to quit"); + ZEN_CONSOLE("Zen Server running (http.sys). Press ESC or Q to quit"); } do @@ -1525,7 +1521,7 @@ HttpSysTransaction::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesTran { if (m_HandlerRequest.has_value()) { - m_HttpServer.m_RequestLog.info("{} {}", ToString(m_HandlerRequest->RequestVerb()), m_HandlerRequest->RelativeUri()); + ZEN_LOG_INFO(m_HttpServer.m_RequestLog, "{} {}", ToString(m_HandlerRequest->RequestVerb()), m_HandlerRequest->RelativeUri()); } } diff --git a/src/zenserver-test/zenserver-test.cpp b/src/zenserver-test/zenserver-test.cpp index 056bf82cd..9df683701 100644 --- a/src/zenserver-test/zenserver-test.cpp +++ b/src/zenserver-test/zenserver-test.cpp @@ -24,6 +24,7 @@ #include <zenhttp/zenhttp.h> #include <zenutil/cache/cache.h> #include <zenutil/cache/cacherequests.h> +#include <zenutil/logging/testformatter.h> #include <zenutil/zenserverprocess.h> #if ZEN_USE_MIMALLOC @@ -94,155 +95,6 @@ struct Concurrency #endif ////////////////////////////////////////////////////////////////////////// -// -// Custom logging -- test code, this should be tweaked -// - -namespace logging { -using namespace spdlog; -using namespace spdlog::details; -using namespace std::literals; - -class full_test_formatter final : public spdlog::formatter -{ -public: - full_test_formatter(std::string_view LogId, std::chrono::time_point<std::chrono::system_clock> Epoch) : m_Epoch(Epoch), m_LogId(LogId) - { - } - - virtual std::unique_ptr<formatter> clone() const override { return std::make_unique<full_test_formatter>(m_LogId, m_Epoch); } - - static constexpr bool UseDate = false; - - virtual void format(const details::log_msg& msg, memory_buf_t& dest) override - { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::seconds; - - if constexpr (UseDate) - { - auto secs = std::chrono::duration_cast<seconds>(msg.time.time_since_epoch()); - if (secs != m_LastLogSecs) - { - m_CachedTm = os::localtime(log_clock::to_time_t(msg.time)); - m_LastLogSecs = secs; - } - } - - const auto& tm_time = m_CachedTm; - - // cache the date/time part for the next second. - auto duration = msg.time - m_Epoch; - auto secs = duration_cast<seconds>(duration); - - if (m_CacheTimestamp != secs || m_CachedDatetime.size() == 0) - { - m_CachedDatetime.clear(); - m_CachedDatetime.push_back('['); - - if constexpr (UseDate) - { - fmt_helper::append_int(tm_time.tm_year + 1900, m_CachedDatetime); - m_CachedDatetime.push_back('-'); - - fmt_helper::pad2(tm_time.tm_mon + 1, m_CachedDatetime); - m_CachedDatetime.push_back('-'); - - fmt_helper::pad2(tm_time.tm_mday, m_CachedDatetime); - m_CachedDatetime.push_back(' '); - - fmt_helper::pad2(tm_time.tm_hour, m_CachedDatetime); - m_CachedDatetime.push_back(':'); - - fmt_helper::pad2(tm_time.tm_min, m_CachedDatetime); - m_CachedDatetime.push_back(':'); - - fmt_helper::pad2(tm_time.tm_sec, m_CachedDatetime); - } - else - { - int Count = int(secs.count()); - - const int LogSecs = Count % 60; - Count /= 60; - - const int LogMins = Count % 60; - Count /= 60; - - const int LogHours = Count; - - fmt_helper::pad2(LogHours, m_CachedDatetime); - m_CachedDatetime.push_back(':'); - fmt_helper::pad2(LogMins, m_CachedDatetime); - m_CachedDatetime.push_back(':'); - fmt_helper::pad2(LogSecs, m_CachedDatetime); - } - - m_CachedDatetime.push_back('.'); - - m_CacheTimestamp = secs; - } - - dest.append(m_CachedDatetime.begin(), m_CachedDatetime.end()); - - auto millis = fmt_helper::time_fraction<milliseconds>(msg.time); - fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); - dest.push_back(']'); - dest.push_back(' '); - - if (!m_LogId.empty()) - { - dest.push_back('['); - fmt_helper::append_string_view(m_LogId, dest); - dest.push_back(']'); - dest.push_back(' '); - } - - // append logger name if exists - if (msg.logger_name.size() > 0) - { - dest.push_back('['); - fmt_helper::append_string_view(msg.logger_name, dest); - dest.push_back(']'); - dest.push_back(' '); - } - - dest.push_back('['); - // wrap the level name with color - msg.color_range_start = dest.size(); - fmt_helper::append_string_view(level::to_string_view(msg.level), dest); - msg.color_range_end = dest.size(); - dest.push_back(']'); - dest.push_back(' '); - - // add source location if present - if (!msg.source.empty()) - { - dest.push_back('['); - const char* filename = details::short_filename_formatter<details::null_scoped_padder>::basename(msg.source.filename); - fmt_helper::append_string_view(filename, dest); - dest.push_back(':'); - fmt_helper::append_int(msg.source.line, dest); - dest.push_back(']'); - dest.push_back(' '); - } - - fmt_helper::append_string_view(msg.payload, dest); - fmt_helper::append_string_view("\n"sv, dest); - } - -private: - std::chrono::time_point<std::chrono::system_clock> m_Epoch; - std::tm m_CachedTm; - std::chrono::seconds m_LastLogSecs; - std::chrono::seconds m_CacheTimestamp{0}; - memory_buf_t m_CachedDatetime; - std::string m_LogId; -}; -} // namespace logging - -////////////////////////////////////////////////////////////////////////// #if ZEN_WITH_TESTS zen::ZenServerEnvironment TestEnv; @@ -262,8 +114,8 @@ main(int argc, char** argv) zen::logging::InitializeLogging(); - spdlog::set_level(spdlog::level::debug); - spdlog::set_formatter(std::make_unique< ::logging::full_test_formatter>("test", std::chrono::system_clock::now())); + zen::logging::SetLogLevel(zen::logging::level::Debug); + spdlog::set_formatter(std::make_unique<zen::logging::full_test_formatter>("test", std::chrono::system_clock::now())); std::filesystem::path ProgramBaseDir = std::filesystem::path(argv[0]).parent_path(); std::filesystem::path TestBaseDir = ProgramBaseDir.parent_path().parent_path() / ".test"; diff --git a/src/zenserver/admin/admin.cpp b/src/zenserver/admin/admin.cpp index 83f33d4ea..00a5c79ed 100644 --- a/src/zenserver/admin/admin.cpp +++ b/src/zenserver/admin/admin.cpp @@ -5,6 +5,7 @@ #include <zencore/compactbinarybuilder.h> #include <zencore/fmtutils.h> #include <zencore/jobqueue.h> +#include <zencore/logging.h> #include <zencore/string.h> #if ZEN_WITH_TRACE @@ -23,10 +24,6 @@ #include <chrono> -ZEN_THIRD_PARTY_INCLUDES_START -#include <spdlog/spdlog.h> -ZEN_THIRD_PARTY_INCLUDES_END - namespace zen { HttpAdminService::HttpAdminService(GcScheduler& Scheduler, @@ -563,8 +560,8 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler, m_Router.RegisterRoute( "logs", [this](HttpRouterRequest& Req) { - CbObjectWriter Obj; - spdlog::string_view_t LogLevel = spdlog::level::to_string_view(spdlog::get_level()); + CbObjectWriter Obj; + auto LogLevel = logging::level::ToStringView(logging::GetLogLevel()); Obj.AddString("loglevel", std::string_view(LogLevel.data(), LogLevel.size())); Obj.AddString("Logfile", PathToUtf8(m_LogPaths.AbsLogPath)); Obj.BeginObject("cache"); @@ -615,15 +612,15 @@ HttpAdminService::HttpAdminService(GcScheduler& Scheduler, } if (std::string Param(Params.GetValue("loglevel")); Param.empty() == false) { - spdlog::level::level_enum NewLevel = spdlog::level::from_str(Param); - spdlog::string_view_t LogLevel = spdlog::level::to_string_view(NewLevel); + logging::level::LogLevel NewLevel = logging::level::ParseLogLevelString(Param); + std::string_view LogLevel = logging::level::ToStringView(NewLevel); if (LogLevel != Param) { return Req.ServerRequest().WriteResponse(HttpResponseCode::BadRequest, HttpContentType::kText, fmt::format("Invalid log level '{}'", Param)); } - spdlog::set_level(NewLevel); + logging::SetLogLevel(NewLevel); if (StringBuilder.Size() > 0) { StringBuilder.Append(", "); diff --git a/src/zenserver/cache/httpstructuredcache.h b/src/zenserver/cache/httpstructuredcache.h index 75ae1711f..57a533029 100644 --- a/src/zenserver/cache/httpstructuredcache.h +++ b/src/zenserver/cache/httpstructuredcache.h @@ -12,10 +12,6 @@ #include <memory> #include <vector> -namespace spdlog { -class logger; -} - namespace zen { struct CacheChunkRequest; @@ -178,8 +174,8 @@ private: bool AreDiskWritesAllowed() const; - spdlog::logger& Log() { return m_Log; } - spdlog::logger& m_Log; + LoggerRef Log() { return m_Log; } + LoggerRef m_Log; ZenCacheStore& m_CacheStore; HttpStatsService& m_StatsService; HttpStatusService& m_StatusService; diff --git a/src/zenserver/cache/structuredcachestore.cpp b/src/zenserver/cache/structuredcachestore.cpp index db6156ea1..236a0e1d7 100644 --- a/src/zenserver/cache/structuredcachestore.cpp +++ b/src/zenserver/cache/structuredcachestore.cpp @@ -40,6 +40,7 @@ ZEN_THIRD_PARTY_INCLUDES_END # include <zencore/workthreadpool.h> # include <zenstore/cidstore.h> # include <random> +# include <unordered_map> #endif namespace zen { @@ -310,9 +311,9 @@ ZenCacheStore::LogWorker() { SetCurrentThreadName("ZenCacheStore::LogWorker"); - spdlog::logger& ZCacheLog(logging::Get("z$")); + LoggerRef ZCacheLog(logging::Get("z$")); - auto Log = [&ZCacheLog]() { return ZCacheLog; }; + auto Log = [&ZCacheLog]() -> LoggerRef { return ZCacheLog; }; std::vector<AccessLogItem> Items; while (true) diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index 43d517520..8fe4213cb 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -23,8 +23,12 @@ ZEN_THIRD_PARTY_INCLUDES_END # include <conio.h> #else # include <pwd.h> +# include <unistd.h> #endif +#include <unordered_map> +#include <unordered_set> + #if ZEN_PLATFORM_WINDOWS // Used for getting My Documents for default data directory @@ -1325,9 +1329,9 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) if (result.count("help")) { - zen::logging::ConsoleLog().info("{}", options.help()); + ZEN_CONSOLE("{}", options.help()); #if ZEN_PLATFORM_WINDOWS - zen::logging::ConsoleLog().info("Press any key to exit!"); + ZEN_CONSOLE("Press any key to exit!"); _getch(); #else // Assume the user's in a terminal on all other platforms and that @@ -1368,13 +1372,13 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) } catch (cxxopts::OptionParseException& e) { - zen::logging::ConsoleLog().error("Error parsing zenserver arguments: {}\n\n{}", e.what(), options.help()); + ZEN_CONSOLE_ERROR("Error parsing zenserver arguments: {}\n\n{}", e.what(), options.help()); throw; } catch (zen::OptionParseException& e) { - zen::logging::ConsoleLog().error("Error parsing zenserver arguments: {}\n\n{}", e.what(), options.help()); + ZEN_CONSOLE_ERROR("Error parsing zenserver arguments: {}\n\n{}", e.what(), options.help()); throw; } diff --git a/src/zenserver/diag/diagsvcs.cpp b/src/zenserver/diag/diagsvcs.cpp index 93c2eafc3..1d62b4d17 100644 --- a/src/zenserver/diag/diagsvcs.cpp +++ b/src/zenserver/diag/diagsvcs.cpp @@ -11,7 +11,10 @@ #include <fstream> #include <sstream> +ZEN_THIRD_PARTY_INCLUDES_START +#include <spdlog/logger.h> #include <json11.hpp> +ZEN_THIRD_PARTY_INCLUDES_END namespace zen { @@ -75,7 +78,7 @@ HttpHealthService::HttpHealthService() [this](HttpRouterRequest& RoutedReq) { HttpServerRequest& HttpReq = RoutedReq.ServerRequest(); - zen::Log().flush(); + zen::Log().SpdLogger->flush(); std::filesystem::path Path = [&] { RwLock::SharedLockScope _(m_InfoLock); diff --git a/src/zenserver/diag/logging.cpp b/src/zenserver/diag/logging.cpp index 6a27ea13e..e2d57b840 100644 --- a/src/zenserver/diag/logging.cpp +++ b/src/zenserver/diag/logging.cpp @@ -11,6 +11,10 @@ #include <zenutil/logging.h> #include <zenutil/logging/rotatingfilesink.h> +ZEN_THIRD_PARTY_INCLUDES_START +#include <spdlog/spdlog.h> +ZEN_THIRD_PARTY_INCLUDES_END + namespace zen { void diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp index b83964319..69cc2bbf5 100644 --- a/src/zenserver/main.cpp +++ b/src/zenserver/main.cpp @@ -244,7 +244,7 @@ ZenEntryPoint::Run() } catch (std::exception& e) { - SPDLOG_CRITICAL("Caught exception in main: {}", e.what()); + ZEN_CRITICAL("Caught exception in main: {}", e.what()); if (!IsApplicationExitRequested()) { RequestApplicationExit(1); @@ -297,7 +297,7 @@ test_main(int argc, char** argv) zen::z$service_forcelink(); zen::logging::InitializeLogging(); - spdlog::set_level(spdlog::level::debug); + zen::logging::SetLogLevel(zen::logging::level::Debug); zen::MaximizeOpenFileCount(); diff --git a/src/zenserver/projectstore/httpprojectstore.h b/src/zenserver/projectstore/httpprojectstore.h index ac12d4d7c..9998ae83e 100644 --- a/src/zenserver/projectstore/httpprojectstore.h +++ b/src/zenserver/projectstore/httpprojectstore.h @@ -81,9 +81,9 @@ private: void HandleOplogDetailsRequest(HttpRouterRequest& Req); void HandleOplogOpDetailsRequest(HttpRouterRequest& Req); - inline spdlog::logger& Log() { return m_Log; } + inline LoggerRef Log() { return m_Log; } - spdlog::logger& m_Log; + LoggerRef m_Log; CidStore& m_CidStore; HttpRequestRouter m_Router; Ref<ProjectStore> m_ProjectStore; diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp index ba30dcd7b..9fedd9165 100644 --- a/src/zenserver/projectstore/projectstore.cpp +++ b/src/zenserver/projectstore/projectstore.cpp @@ -454,7 +454,7 @@ struct ProjectStore::OplogStorage : public RefCounted uint32_t GetMaxLsn() const { return m_MaxLsn.load(); } - spdlog::logger& Log() { return m_OwnerOplog->Log(); } + LoggerRef Log() { return m_OwnerOplog->Log(); } private: ProjectStore::Oplog* m_OwnerOplog; @@ -1349,7 +1349,7 @@ ProjectStore::Project::WriteAccessTimes() } } -spdlog::logger& +LoggerRef ProjectStore::Project::Log() { return m_ProjectStore->Log(); diff --git a/src/zenserver/projectstore/projectstore.h b/src/zenserver/projectstore/projectstore.h index fbff1444d..fe1068485 100644 --- a/src/zenserver/projectstore/projectstore.h +++ b/src/zenserver/projectstore/projectstore.h @@ -13,6 +13,7 @@ ZEN_THIRD_PARTY_INCLUDES_START ZEN_THIRD_PARTY_INCLUDES_END #include <map> +#include <unordered_map> namespace zen { @@ -123,7 +124,7 @@ public: const std::filesystem::path& TempPath() const { return m_TempPath; } const std::filesystem::path& MarkerPath() const { return m_MarkerPath; } - spdlog::logger& Log() { return m_OuterProject->Log(); } + LoggerRef Log() { return m_OuterProject->Log(); } void Flush(); void ScrubStorage(ScrubContext& Ctx) const; void GatherReferences(GcContext& GcCtx); @@ -242,7 +243,7 @@ public: [[nodiscard]] static bool Exists(const std::filesystem::path& BasePath); void Flush(); void ScrubStorage(ScrubContext& Ctx); - spdlog::logger& Log(); + LoggerRef Log(); void GatherReferences(GcContext& GcCtx); uint64_t TotalSize() const; bool PrepareForDelete(std::filesystem::path& OutDeletePath); @@ -285,7 +286,7 @@ public: void DiscoverProjects(); void IterateProjects(std::function<void(Project& Prj)>&& Fn); - spdlog::logger& Log() { return m_Log; } + LoggerRef Log() { return m_Log; } const std::filesystem::path& BasePath() const { return m_ProjectBasePath; } virtual void GatherReferences(GcContext& GcCtx) override; @@ -368,7 +369,7 @@ public: bool AreDiskWritesAllowed() const; private: - spdlog::logger& m_Log; + LoggerRef m_Log; GcManager& m_Gc; CidStore& m_CidStore; JobQueue& m_JobQueue; diff --git a/src/zenserver/sentryintegration.cpp b/src/zenserver/sentryintegration.cpp index 10a05c3c8..755fe97db 100644 --- a/src/zenserver/sentryintegration.cpp +++ b/src/zenserver/sentryintegration.cpp @@ -16,6 +16,10 @@ # include <pwd.h> #endif +ZEN_THIRD_PARTY_INCLUDES_START +#include <spdlog/spdlog.h> +ZEN_THIRD_PARTY_INCLUDES_END + #if ZEN_USE_SENTRY # define SENTRY_BUILD_STATIC 1 ZEN_THIRD_PARTY_INCLUDES_START @@ -162,23 +166,23 @@ SentryLogFunction(sentry_level_t Level, const char* Message, va_list Args, [[may switch (Level) { case SENTRY_LEVEL_DEBUG: - ConsoleLog().debug("sentry: {}", MessagePtr); + ZEN_CONSOLE_DEBUG("sentry: {}", MessagePtr); break; case SENTRY_LEVEL_INFO: - ConsoleLog().info("sentry: {}", MessagePtr); + ZEN_CONSOLE_INFO("sentry: {}", MessagePtr); break; case SENTRY_LEVEL_WARNING: - ConsoleLog().warn("sentry: {}", MessagePtr); + ZEN_CONSOLE_WARN("sentry: {}", MessagePtr); break; case SENTRY_LEVEL_ERROR: - ConsoleLog().error("sentry: {}", MessagePtr); + ZEN_CONSOLE_ERROR("sentry: {}", MessagePtr); break; case SENTRY_LEVEL_FATAL: - ConsoleLog().critical("sentry: {}", MessagePtr); + ZEN_CONSOLE_CRITICAL("sentry: {}", MessagePtr); break; } } @@ -192,7 +196,7 @@ SentryIntegration::~SentryIntegration() { if (m_IsInitialized && m_SentryErrorCode == 0) { - logging::SetErrorLog(std::shared_ptr<spdlog::logger>()); + logging::SetErrorLog(""); m_SentryAssert.reset(); sentry_close(); } @@ -250,8 +254,8 @@ SentryIntegration::Initialize(std::string SentryDatabasePath, std::string Sentry sentry_set_user(SentryUserObject); } - auto SentrySink = spdlog::create<sentry::sentry_sink>("sentry"); - logging::SetErrorLog(std::move(SentrySink)); + m_SentryLogger = spdlog::create<sentry::sentry_sink>("sentry"); + logging::SetErrorLog("sentry"); m_SentryAssert = std::make_unique<sentry::SentryAssertImpl>(); } diff --git a/src/zenserver/sentryintegration.h b/src/zenserver/sentryintegration.h index f25cf5dce..fddba8882 100644 --- a/src/zenserver/sentryintegration.h +++ b/src/zenserver/sentryintegration.h @@ -18,6 +18,10 @@ # include <memory> +ZEN_THIRD_PARTY_INCLUDES_START +# include <spdlog/logger.h> +ZEN_THIRD_PARTY_INCLUDES_END + namespace sentry { struct SentryAssertImpl; @@ -42,6 +46,7 @@ private: bool m_AllowPII = false; std::unique_ptr<sentry::SentryAssertImpl> m_SentryAssert; std::string m_SentryUserName; + std::shared_ptr<spdlog::logger> m_SentryLogger; }; } // namespace zen diff --git a/src/zenserver/upstream/jupiter.h b/src/zenserver/upstream/jupiter.h index ca84905d2..467f28501 100644 --- a/src/zenserver/upstream/jupiter.h +++ b/src/zenserver/upstream/jupiter.h @@ -131,15 +131,15 @@ public: CloudCacheClient& Client() { return *m_CacheClient; }; private: - inline spdlog::logger& Log() { return m_Log; } - cpr::Session& GetSession(); - CloudCacheAccessToken GetAccessToken(bool RefreshToken = false); + inline LoggerRef Log() { return m_Log; } + cpr::Session& GetSession(); + CloudCacheAccessToken GetAccessToken(bool RefreshToken = false); CloudCacheResult CacheTypeExists(std::string_view Namespace, std::string_view TypeId, const IoHash& Key); CloudCacheExistsResult CacheTypeExists(std::string_view Namespace, std::string_view TypeId, const std::set<IoHash>& Keys); - spdlog::logger& m_Log; + LoggerRef m_Log; RefPtr<CloudCacheClient> m_CacheClient; detail::CloudCacheSessionState* m_SessionState; }; @@ -195,10 +195,10 @@ public: std::string_view ComputeCluster() const { return m_ComputeCluster; } std::string_view ServiceUrl() const { return m_ServiceUrl; } - spdlog::logger& Logger() { return m_Log; } + LoggerRef Logger() { return m_Log; } private: - spdlog::logger& m_Log; + LoggerRef m_Log; std::string m_ServiceUrl; std::string m_DefaultDdcNamespace; std::string m_DefaultBlobStoreNamespace; diff --git a/src/zenserver/upstream/upstreamcache.cpp b/src/zenserver/upstream/upstreamcache.cpp index 5f711d0bc..8e00f86b0 100644 --- a/src/zenserver/upstream/upstreamcache.cpp +++ b/src/zenserver/upstream/upstreamcache.cpp @@ -29,7 +29,6 @@ #include <atomic> #include <shared_mutex> #include <thread> -#include <unordered_map> namespace zen { @@ -753,10 +752,10 @@ namespace detail { return {.Bytes = TotalBytes, .ElapsedSeconds = TotalElapsedSeconds, .Success = true}; } - spdlog::logger& Log() { return m_Log; } + LoggerRef Log() { return m_Log; } AuthMgr& m_AuthMgr; - spdlog::logger& m_Log; + LoggerRef m_Log; UpstreamEndpointInfo m_Info; UpstreamStatus m_Status; UpstreamEndpointStats m_Stats; @@ -1460,9 +1459,9 @@ namespace detail { return m_Endpoints.front(); } - spdlog::logger& Log() { return m_Log; } + LoggerRef Log() { return m_Log; } - spdlog::logger& m_Log; + LoggerRef m_Log; UpstreamEndpointInfo m_Info; UpstreamStatus m_Status; UpstreamEndpointStats m_Stats; @@ -2078,7 +2077,7 @@ private: } } - spdlog::logger& Log() { return m_Log; } + LoggerRef Log() { return m_Log; } using UpstreamQueue = BlockingQueue<UpstreamCacheRecord>; @@ -2103,7 +2102,7 @@ private: } }; - spdlog::logger& m_Log; + LoggerRef m_Log; UpstreamCacheOptions m_Options; ZenCacheStore& m_CacheStore; CidStore& m_CidStore; diff --git a/src/zenserver/upstream/zen.h b/src/zenserver/upstream/zen.h index bfba8fa98..c1e4fbd0f 100644 --- a/src/zenserver/upstream/zen.h +++ b/src/zenserver/upstream/zen.h @@ -20,10 +20,6 @@ ZEN_THIRD_PARTY_INCLUDES_END struct ZenCacheValue; -namespace spdlog { -class logger; -} - namespace zen { class CbObjectWriter; @@ -85,9 +81,9 @@ public: ZenCacheResult InvokeRpc(const CbPackage& Package); private: - inline spdlog::logger& Log() { return m_Log; } + inline LoggerRef Log() { return m_Log; } - spdlog::logger& m_Log; + LoggerRef m_Log; Ref<ZenStructuredCacheClient> m_Client; detail::ZenCacheSessionState* m_SessionState; }; @@ -105,10 +101,10 @@ public: std::string_view ServiceUrl() const { return m_ServiceUrl; } - inline spdlog::logger& Log() { return m_Log; } + inline LoggerRef Log() { return m_Log; } private: - spdlog::logger& m_Log; + LoggerRef m_Log; std::string m_ServiceUrl; std::chrono::milliseconds m_ConnectTimeout; std::chrono::milliseconds m_Timeout; diff --git a/src/zenserver/zenserver.h b/src/zenserver/zenserver.h index de069be69..7da536708 100644 --- a/src/zenserver/zenserver.h +++ b/src/zenserver/zenserver.h @@ -10,9 +10,7 @@ #include <string_view> ZEN_THIRD_PARTY_INCLUDES_START -#include <fmt/format.h> #include <asio.hpp> -#include <lua.hpp> ZEN_THIRD_PARTY_INCLUDES_END ////////////////////////////////////////////////////////////////////////// diff --git a/src/zenstore/compactcas.h b/src/zenstore/compactcas.h index 9f3aa6b07..3ed883801 100644 --- a/src/zenstore/compactcas.h +++ b/src/zenstore/compactcas.h @@ -2,6 +2,7 @@ #pragma once +#include <zencore/logbase.h> #include <zencore/zencore.h> #include <zenstore/blockstore.h> #include <zenstore/caslog.h> @@ -16,10 +17,6 @@ ZEN_THIRD_PARTY_INCLUDES_START #include <tsl/robin_map.h> ZEN_THIRD_PARTY_INCLUDES_END -namespace spdlog { -class logger; -} - namespace zen { ////////////////////////////////////////////////////////////////////////// @@ -82,9 +79,9 @@ private: void OpenContainer(bool IsNewStore); void CompactIndex(RwLock::ExclusiveLockScope&); - spdlog::logger& Log() { return m_Log; } + LoggerRef Log() { return m_Log; } - spdlog::logger& m_Log; + LoggerRef m_Log; GcManager& m_Gc; std::filesystem::path m_RootDirectory; uint64_t m_PayloadAlignment = 1u << 4; diff --git a/src/zenstore/filecas.h b/src/zenstore/filecas.h index c39a39bb7..cb1347580 100644 --- a/src/zenstore/filecas.h +++ b/src/zenstore/filecas.h @@ -16,10 +16,6 @@ #include <atomic> #include <functional> -namespace spdlog { -class logger; -} - namespace zen { class BasicFile; @@ -48,10 +44,10 @@ struct FileCasStrategy final : public GcStorage, public GcReferenceStore virtual GcReferencePruner* CreateReferencePruner(GcCtx& Ctx, GcReferenceStoreStats& Stats) override; private: - void MakeIndexSnapshot(); - uint64_t ReadIndexFile(const std::filesystem::path& IndexPath, uint32_t& OutVersion); - uint64_t ReadLog(const std::filesystem::path& LogPath, uint64_t LogPosition); - spdlog::logger& Log() { return m_Log; } + void MakeIndexSnapshot(); + uint64_t ReadIndexFile(const std::filesystem::path& IndexPath, uint32_t& OutVersion); + uint64_t ReadLog(const std::filesystem::path& LogPath, uint64_t LogPosition); + LoggerRef Log() { return m_Log; } struct IndexEntry { @@ -61,7 +57,7 @@ private: CasStore::InsertResult InsertChunkData(const void* ChunkData, size_t ChunkSize, const IoHash& ChunkHash); - spdlog::logger& m_Log; + LoggerRef m_Log; GcManager& m_Gc; std::filesystem::path m_RootDirectory; RwLock m_Lock; diff --git a/src/zenstore/include/zenstore/gc.h b/src/zenstore/include/zenstore/gc.h index 1b9929216..409c9b4d6 100644 --- a/src/zenstore/include/zenstore/gc.h +++ b/src/zenstore/include/zenstore/gc.h @@ -3,6 +3,7 @@ #pragma once #include <zencore/iohash.h> +#include <zencore/logbase.h> #include <zencore/thread.h> #include <zenstore/caslog.h> #include <zenstore/scrubcontext.h> @@ -24,10 +25,6 @@ ZEN_THIRD_PARTY_INCLUDES_START #include <tsl/robin_set.h> ZEN_THIRD_PARTY_INCLUDES_END -namespace spdlog { -class logger; -} - namespace zen { class CidStore; @@ -360,8 +357,8 @@ public: void SetDiskWriteBlocker(const DiskWriteBlocker* Monitor) { m_DiskWriteBlocker = Monitor; } private: - spdlog::logger& Log() { return m_Log; } - spdlog::logger& m_Log; + LoggerRef Log() { return m_Log; } + LoggerRef m_Log; mutable RwLock m_Lock; std::vector<GcContributor*> m_GcContribs; std::vector<GcStorage*> m_GcStorage; @@ -483,19 +480,19 @@ public: bool TriggerScrub(const TriggerScrubParams& Params); private: - void SchedulerThread(); - void CollectGarbage(const GcClock::TimePoint& CacheExpireTime, - const GcClock::TimePoint& ProjectStoreExpireTime, - bool Delete, - bool CollectSmallObjects, - bool SkipCid, - GcVersion UseGCVersion); - void ScrubStorage(bool DoDelete, std::chrono::seconds TimeSlice); - spdlog::logger& Log() { return m_Log; } - virtual bool AreDiskWritesAllowed() const override { return !m_AreDiskWritesBlocked.load(); } - DiskSpace CheckDiskSpace(); - - spdlog::logger& m_Log; + void SchedulerThread(); + void CollectGarbage(const GcClock::TimePoint& CacheExpireTime, + const GcClock::TimePoint& ProjectStoreExpireTime, + bool Delete, + bool CollectSmallObjects, + bool SkipCid, + GcVersion UseGCVersion); + void ScrubStorage(bool DoDelete, std::chrono::seconds TimeSlice); + LoggerRef Log() { return m_Log; } + virtual bool AreDiskWritesAllowed() const override { return !m_AreDiskWritesBlocked.load(); } + DiskSpace CheckDiskSpace(); + + LoggerRef m_Log; GcManager& m_GcManager; GcSchedulerConfig m_Config; GcClock::TimePoint m_LastGcTime{}; diff --git a/src/zenutil/include/zenutil/logging/fullformatter.h b/src/zenutil/include/zenutil/logging/fullformatter.h index 9ddb8067e..498ecd143 100644 --- a/src/zenutil/include/zenutil/logging/fullformatter.h +++ b/src/zenutil/include/zenutil/logging/fullformatter.h @@ -4,20 +4,15 @@ #include <zencore/zencore.h> -#include <spdlog/formatter.h> -#include <spdlog/logger.h> #include <string_view> ZEN_THIRD_PARTY_INCLUDES_START +#include <spdlog/formatter.h> #include <spdlog/pattern_formatter.h> ZEN_THIRD_PARTY_INCLUDES_END namespace zen::logging { -using namespace spdlog; -using namespace spdlog::details; -using namespace std::literals; - class full_formatter final : public spdlog::formatter { public: @@ -27,18 +22,16 @@ public: static constexpr bool UseDate = false; - virtual void format(const details::log_msg& msg, memory_buf_t& dest) override + virtual void format(const spdlog::details::log_msg& msg, spdlog::memory_buf_t& dest) override { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::seconds; + using namespace std::literals; if constexpr (UseDate) { - auto secs = std::chrono::duration_cast<seconds>(msg.time.time_since_epoch()); + auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch()); if (secs != m_LastLogSecs) { - m_CachedTm = os::localtime(log_clock::to_time_t(msg.time)); + m_CachedTm = spdlog::details::os::localtime(spdlog::log_clock::to_time_t(msg.time)); m_LastLogSecs = secs; } } @@ -47,7 +40,7 @@ public: // cache the date/time part for the next second. auto duration = msg.time - m_Epoch; - auto secs = duration_cast<seconds>(duration); + auto secs = std::chrono::duration_cast<std::chrono::seconds>(duration); if (m_CacheTimestamp != secs || m_CachedDatetime.size() == 0) { @@ -56,22 +49,22 @@ public: if constexpr (UseDate) { - fmt_helper::append_int(tm_time.tm_year + 1900, m_CachedDatetime); + spdlog::details::fmt_helper::append_int(tm_time.tm_year + 1900, m_CachedDatetime); m_CachedDatetime.push_back('-'); - fmt_helper::pad2(tm_time.tm_mon + 1, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(tm_time.tm_mon + 1, m_CachedDatetime); m_CachedDatetime.push_back('-'); - fmt_helper::pad2(tm_time.tm_mday, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(tm_time.tm_mday, m_CachedDatetime); m_CachedDatetime.push_back(' '); - fmt_helper::pad2(tm_time.tm_hour, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(tm_time.tm_hour, m_CachedDatetime); m_CachedDatetime.push_back(':'); - fmt_helper::pad2(tm_time.tm_min, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(tm_time.tm_min, m_CachedDatetime); m_CachedDatetime.push_back(':'); - fmt_helper::pad2(tm_time.tm_sec, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(tm_time.tm_sec, m_CachedDatetime); } else { @@ -85,11 +78,11 @@ public: const int LogHours = Count; - fmt_helper::pad2(LogHours, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(LogHours, m_CachedDatetime); m_CachedDatetime.push_back(':'); - fmt_helper::pad2(LogMins, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(LogMins, m_CachedDatetime); m_CachedDatetime.push_back(':'); - fmt_helper::pad2(LogSecs, m_CachedDatetime); + spdlog::details::fmt_helper::pad2(LogSecs, m_CachedDatetime); } m_CachedDatetime.push_back('.'); @@ -99,15 +92,15 @@ public: dest.append(m_CachedDatetime.begin(), m_CachedDatetime.end()); - auto millis = fmt_helper::time_fraction<milliseconds>(msg.time); - fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); + auto millis = spdlog::details::fmt_helper::time_fraction<std::chrono::milliseconds>(msg.time); + spdlog::details::fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); dest.push_back(']'); dest.push_back(' '); if (!m_LogId.empty()) { dest.push_back('['); - fmt_helper::append_string_view(m_LogId, dest); + spdlog::details::fmt_helper::append_string_view(m_LogId, dest); dest.push_back(']'); dest.push_back(' '); } @@ -116,7 +109,7 @@ public: if (msg.logger_name.size() > 0) { dest.push_back('['); - fmt_helper::append_string_view(msg.logger_name, dest); + spdlog::details::fmt_helper::append_string_view(msg.logger_name, dest); dest.push_back(']'); dest.push_back(' '); } @@ -124,7 +117,7 @@ public: dest.push_back('['); // wrap the level name with color msg.color_range_start = dest.size(); - fmt_helper::append_string_view(level::to_string_view(msg.level), dest); + spdlog::details::fmt_helper::append_string_view(spdlog::level::to_string_view(msg.level), dest); msg.color_range_end = dest.size(); dest.push_back(']'); dest.push_back(' '); @@ -133,16 +126,17 @@ public: if (!msg.source.empty()) { dest.push_back('['); - const char* filename = details::short_filename_formatter<details::null_scoped_padder>::basename(msg.source.filename); - fmt_helper::append_string_view(filename, dest); + const char* filename = + spdlog::details::short_filename_formatter<spdlog::details::null_scoped_padder>::basename(msg.source.filename); + spdlog::details::fmt_helper::append_string_view(filename, dest); dest.push_back(':'); - fmt_helper::append_int(msg.source.line, dest); + spdlog::details::fmt_helper::append_int(msg.source.line, dest); dest.push_back(']'); dest.push_back(' '); } - fmt_helper::append_string_view(msg.payload, dest); - fmt_helper::append_string_view("\n"sv, dest); + spdlog::details::fmt_helper::append_string_view(msg.payload, dest); + spdlog::details::fmt_helper::append_string_view("\n"sv, dest); } private: @@ -150,7 +144,7 @@ private: std::tm m_CachedTm; std::chrono::seconds m_LastLogSecs; std::chrono::seconds m_CacheTimestamp{0}; - memory_buf_t m_CachedDatetime; + spdlog::memory_buf_t m_CachedDatetime; std::string m_LogId; }; diff --git a/src/zenutil/include/zenutil/logging/jsonformatter.h b/src/zenutil/include/zenutil/logging/jsonformatter.h index 5f7d4853d..40fdb94e2 100644 --- a/src/zenutil/include/zenutil/logging/jsonformatter.h +++ b/src/zenutil/include/zenutil/logging/jsonformatter.h @@ -4,12 +4,10 @@ #include <zencore/zencore.h> -#include <spdlog/formatter.h> -#include <spdlog/logger.h> #include <string_view> ZEN_THIRD_PARTY_INCLUDES_START -#include <spdlog/pattern_formatter.h> +#include <spdlog/formatter.h> ZEN_THIRD_PARTY_INCLUDES_END namespace zen::logging { @@ -166,4 +164,4 @@ private: std::string m_LogId; }; -} // namespace zen::logging
\ No newline at end of file +} // namespace zen::logging diff --git a/src/zenutil/include/zenutil/logging/testformatter.h b/src/zenutil/include/zenutil/logging/testformatter.h new file mode 100644 index 000000000..39fc44e75 --- /dev/null +++ b/src/zenutil/include/zenutil/logging/testformatter.h @@ -0,0 +1,146 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <spdlog/spdlog.h> + +namespace zen::logging { + +class full_test_formatter final : public spdlog::formatter +{ +public: + full_test_formatter(std::string_view LogId, std::chrono::time_point<std::chrono::system_clock> Epoch) : m_Epoch(Epoch), m_LogId(LogId) + { + } + + virtual std::unique_ptr<formatter> clone() const override { return std::make_unique<full_test_formatter>(m_LogId, m_Epoch); } + + static constexpr bool UseDate = false; + + virtual void format(const spdlog::details::log_msg& msg, spdlog::memory_buf_t& dest) override + { + using namespace std::literals; + + if constexpr (UseDate) + { + auto secs = std::chrono::duration_cast<std::chrono::seconds>(msg.time.time_since_epoch()); + if (secs != m_LastLogSecs) + { + m_CachedTm = spdlog::details::os::localtime(spdlog::log_clock::to_time_t(msg.time)); + m_LastLogSecs = secs; + } + } + + const auto& tm_time = m_CachedTm; + + // cache the date/time part for the next second. + auto duration = msg.time - m_Epoch; + auto secs = std::chrono::duration_cast<std::chrono::seconds>(duration); + + if (m_CacheTimestamp != secs || m_CachedDatetime.size() == 0) + { + m_CachedDatetime.clear(); + m_CachedDatetime.push_back('['); + + if constexpr (UseDate) + { + spdlog::details::fmt_helper::append_int(tm_time.tm_year + 1900, m_CachedDatetime); + m_CachedDatetime.push_back('-'); + + spdlog::details::fmt_helper::pad2(tm_time.tm_mon + 1, m_CachedDatetime); + m_CachedDatetime.push_back('-'); + + spdlog::details::fmt_helper::pad2(tm_time.tm_mday, m_CachedDatetime); + m_CachedDatetime.push_back(' '); + + spdlog::details::fmt_helper::pad2(tm_time.tm_hour, m_CachedDatetime); + m_CachedDatetime.push_back(':'); + + spdlog::details::fmt_helper::pad2(tm_time.tm_min, m_CachedDatetime); + m_CachedDatetime.push_back(':'); + + spdlog::details::fmt_helper::pad2(tm_time.tm_sec, m_CachedDatetime); + } + else + { + int Count = int(secs.count()); + + const int LogSecs = Count % 60; + Count /= 60; + + const int LogMins = Count % 60; + Count /= 60; + + const int LogHours = Count; + + spdlog::details::fmt_helper::pad2(LogHours, m_CachedDatetime); + m_CachedDatetime.push_back(':'); + spdlog::details::fmt_helper::pad2(LogMins, m_CachedDatetime); + m_CachedDatetime.push_back(':'); + spdlog::details::fmt_helper::pad2(LogSecs, m_CachedDatetime); + } + + m_CachedDatetime.push_back('.'); + + m_CacheTimestamp = secs; + } + + dest.append(m_CachedDatetime.begin(), m_CachedDatetime.end()); + + auto millis = spdlog::details::fmt_helper::time_fraction<std::chrono::milliseconds>(msg.time); + spdlog::details::fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); + dest.push_back(']'); + dest.push_back(' '); + + if (!m_LogId.empty()) + { + dest.push_back('['); + spdlog::details::fmt_helper::append_string_view(m_LogId, dest); + dest.push_back(']'); + dest.push_back(' '); + } + + // append logger name if exists + if (msg.logger_name.size() > 0) + { + dest.push_back('['); + spdlog::details::fmt_helper::append_string_view(msg.logger_name, dest); + dest.push_back(']'); + dest.push_back(' '); + } + + dest.push_back('['); + // wrap the level name with color + msg.color_range_start = dest.size(); + spdlog::details::fmt_helper::append_string_view(spdlog::level::to_string_view(msg.level), dest); + msg.color_range_end = dest.size(); + dest.push_back(']'); + dest.push_back(' '); + + // add source location if present + if (!msg.source.empty()) + { + dest.push_back('['); + const char* filename = + spdlog::details::short_filename_formatter<spdlog::details::null_scoped_padder>::basename(msg.source.filename); + spdlog::details::fmt_helper::append_string_view(filename, dest); + dest.push_back(':'); + spdlog::details::fmt_helper::append_int(msg.source.line, dest); + dest.push_back(']'); + dest.push_back(' '); + } + + spdlog::details::fmt_helper::append_string_view(msg.payload, dest); + spdlog::details::fmt_helper::append_string_view("\n"sv, dest); + } + +private: + std::chrono::time_point<std::chrono::system_clock> m_Epoch; + std::tm m_CachedTm; + std::chrono::seconds m_LastLogSecs; + std::chrono::seconds m_CacheTimestamp{0}; + spdlog::memory_buf_t m_CachedDatetime; + std::string m_LogId; +}; + +} // namespace zen::logging
\ No newline at end of file diff --git a/src/zenutil/logging.cpp b/src/zenutil/logging.cpp index 4d8dcbca6..512c7901c 100644 --- a/src/zenutil/logging.cpp +++ b/src/zenutil/logging.cpp @@ -7,6 +7,7 @@ ZEN_THIRD_PARTY_INCLUDES_START #include <spdlog/async_logger.h> #include <spdlog/sinks/ansicolor_sink.h> #include <spdlog/sinks/msvc_sink.h> +#include <spdlog/spdlog.h> ZEN_THIRD_PARTY_INCLUDES_END #include <zencore/compactbinary.h> @@ -58,10 +59,10 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) { const int QueueSize = 8192; const int ThreadCount = 1; - spdlog::init_thread_pool(QueueSize, ThreadCount); + spdlog::init_thread_pool(QueueSize, ThreadCount, [&] { SetCurrentThreadName("spdlog_async"); }); - auto AsyncLogger = spdlog::create_async<spdlog::sinks::ansicolor_stdout_sink_mt>("main"); - zen::logging::SetDefault(AsyncLogger); + auto AsyncSink = spdlog::create_async<spdlog::sinks::ansicolor_stdout_sink_mt>("main"); + zen::logging::SetDefault("main"); } // Sinks @@ -87,8 +88,8 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) // Default - auto& DefaultLogger = zen::logging::Default(); - auto& Sinks = DefaultLogger.sinks(); + LoggerRef DefaultLogger = zen::logging::Default(); + auto& Sinks = DefaultLogger.SpdLogger->sinks(); Sinks.clear(); @@ -124,11 +125,11 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) return; } // Bypass zen logging wrapping to reduce potential other error sources - if (auto ErrLogger = zen::logging::ErrorLog(); ErrLogger != nullptr) + if (auto ErrLogger = zen::logging::ErrorLog()) { try { - ErrLogger->log(spdlog::level::err, msg); + ErrLogger.SpdLogger->log(spdlog::level::err, msg); } catch (const std::exception&) { @@ -137,7 +138,7 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) } try { - Log().error(msg); + Log().SpdLogger->error(msg); } catch (const std::exception&) { @@ -192,8 +193,8 @@ ShutdownLogging() { g_FileSink.reset(); - auto& DefaultLogger = zen::logging::Default(); - DefaultLogger.info("log ending at {}", zen::DateTime::Now().ToIso8601()); + auto DefaultLogger = zen::logging::Default(); + ZEN_LOG_INFO(DefaultLogger, "log ending at {}", zen::DateTime::Now().ToIso8601()); zen::logging::ShutdownLogging(); } |