diff options
| author | Stefan Boberg <[email protected]> | 2023-12-06 08:44:46 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-12-06 08:44:46 +0100 |
| commit | 94fc3302c898825d7bc460ad4504577e33f744d9 (patch) | |
| tree | 786ab5da6801dd5aabaca28f503c205af529363f /src | |
| parent | Use correct iterator index when looking up memcached payload in GatherReferen... (diff) | |
| download | zen-94fc3302c898825d7bc460ad4504577e33f744d9.tar.xz zen-94fc3302c898825d7bc460ad4504577e33f744d9.zip | |
logging configuration via command line options (#589)
with these changes it is possible to configure loggers on the command line. For instance:
`xmake run zenserver --log-trace=http_requests,http`
will configure the system so that the `http_request` and `http` loggers are set to TRACE level
Diffstat (limited to 'src')
| -rw-r--r-- | src/zencore/include/zencore/logging.h | 4 | ||||
| -rw-r--r-- | src/zencore/logging.cpp | 77 | ||||
| -rw-r--r-- | src/zenserver/config.cpp | 25 | ||||
| -rw-r--r-- | src/zenserver/config.h | 2 | ||||
| -rw-r--r-- | src/zenserver/diag/logging.cpp | 4 | ||||
| -rw-r--r-- | src/zenutil/logging.cpp | 9 |
6 files changed, 114 insertions, 7 deletions
diff --git a/src/zencore/include/zencore/logging.h b/src/zencore/include/zencore/logging.h index d14d1ab8d..8b76d754c 100644 --- a/src/zencore/include/zencore/logging.h +++ b/src/zencore/include/zencore/logging.h @@ -35,6 +35,10 @@ LoggerRef ErrorLog(); void SetErrorLog(std::string_view LoggerId); LoggerRef Get(std::string_view Name); +void ConfigureLogLevels(level::LogLevel Level, std::string_view Loggers); +void RefreshLogLevels(); +void RefreshLogLevels(level::LogLevel DefaultLevel); + struct LogCategory { inline LogCategory(std::string_view InCategory) : CategoryName(InCategory) {} diff --git a/src/zencore/logging.cpp b/src/zencore/logging.cpp index 025ed4262..0bf07affd 100644 --- a/src/zencore/logging.cpp +++ b/src/zencore/logging.cpp @@ -4,10 +4,14 @@ #include <zencore/string.h> #include <zencore/testing.h> +#include <zencore/thread.h> +ZEN_THIRD_PARTY_INCLUDES_START +#include <spdlog/details/registry.h> #include <spdlog/sinks/null_sink.h> #include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/spdlog.h> +ZEN_THIRD_PARTY_INCLUDES_END #if ZEN_PLATFORM_WINDOWS # pragma section(".zlog$a", read) @@ -46,6 +50,8 @@ LoggingContext::~LoggingContext() { } +////////////////////////////////////////////////////////////////////////// + static inline bool IsErrorLevel(int LogLevel) { @@ -176,8 +182,77 @@ ToStringView(level::LogLevel Level) } // namespace zen::logging::level +////////////////////////////////////////////////////////////////////////// + namespace zen::logging { +RwLock LogLevelsLock; +std::string LogLevels[level::LogLevelCount]; + +void +ConfigureLogLevels(level::LogLevel Level, std::string_view Loggers) +{ + RwLock::ExclusiveLockScope _(LogLevelsLock); + LogLevels[Level] = Loggers; +} + +void +RefreshLogLevels(level::LogLevel* DefaultLevel) +{ + spdlog::details::registry::log_levels Levels; + + { + RwLock::SharedLockScope _(LogLevelsLock); + + for (int i = 0; i < level::LogLevelCount; ++i) + { + level::LogLevel CurrentLevel{i}; + + std::string_view Spec = LogLevels[i]; + + while (!Spec.empty()) + { + std::string LoggerName; + + if (auto CommaPos = Spec.find_first_of(','); CommaPos != std::string_view::npos) + { + LoggerName = Spec.substr(CommaPos + 1); + Spec.remove_prefix(CommaPos + 1); + } + else + { + LoggerName = Spec; + Spec = {}; + } + + Levels[LoggerName] = to_spdlog_level(CurrentLevel); + } + } + } + + if (DefaultLevel) + { + spdlog::level::level_enum SpdDefaultLevel = to_spdlog_level(*DefaultLevel); + spdlog::details::registry::instance().set_levels(Levels, &SpdDefaultLevel); + } + else + { + spdlog::details::registry::instance().set_levels(Levels, nullptr); + } +} + +void +RefreshLogLevels(level::LogLevel DefaultLevel) +{ + RefreshLogLevels(&DefaultLevel); +} + +void +RefreshLogLevels() +{ + RefreshLogLevels(nullptr); +} + void SetLogLevel(level::LogLevel NewLogLevel) { @@ -240,6 +315,7 @@ Get(std::string_view Name) if (!Logger) { Logger = Default().SpdLogger->clone(std::string(Name)); + spdlog::apply_logger_env_levels(Logger); spdlog::register_logger(Logger); } @@ -262,6 +338,7 @@ ConsoleLog() if (!ConLogger) { ConLogger = spdlog::stdout_color_mt("console"); + spdlog::apply_logger_env_levels(ConLogger); ConLogger->set_pattern("%v"); } diff --git a/src/zenserver/config.cpp b/src/zenserver/config.cpp index fe92613f4..3fe0b0c63 100644 --- a/src/zenserver/config.cpp +++ b/src/zenserver/config.cpp @@ -9,6 +9,7 @@ #include <zencore/except.h> #include <zencore/fmtutils.h> #include <zencore/iobuffer.h> +#include <zencore/logging.h> #include <zencore/string.h> #include <zenhttp/zenhttp.h> #include <zenutil/basicfile.h> @@ -519,7 +520,6 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) cxxopts::value<bool>(ServerOptions.IsCleanStart)->default_value("false")); options.add_options()("help", "Show command line help"); options.add_options()("t, test", "Enable test mode", cxxopts::value<bool>(ServerOptions.IsTest)->default_value("false")); - options.add_options()("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(ServerOptions.LogId)); options.add_options()("data-dir", "Specify persistence root", cxxopts::value<std::string>(DataDir)); options.add_options()("snapshot-dir", "Specify a snapshot of server state to mirror into the persistence root at startup", @@ -528,7 +528,6 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) options.add_options()("powercycle", "Exit immediately after initialization is complete", cxxopts::value<bool>(ServerOptions.IsPowerCycle)); - options.add_options()("abslog", "Path to log file", cxxopts::value<std::string>(AbsLogFile)); options.add_options()("config", "Path to Lua config file", cxxopts::value<std::string>(ConfigFile)); options.add_options()("write-config", "Path to output Lua config file", cxxopts::value<std::string>(OutputConfigFile)); options.add_options()("no-sentry", @@ -537,7 +536,21 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) options.add_options()("sentry-allow-personal-info", "Allow personally identifiable information in sentry crash reports", cxxopts::value<bool>(ServerOptions.SentryAllowPII)->default_value("false")); - options.add_options()("quiet", "Disable console logging", cxxopts::value<bool>(ServerOptions.NoConsoleOutput)->default_value("false")); + + // clang-format off + options.add_options("logging") + ("abslog", "Path to log file", cxxopts::value<std::string>(AbsLogFile)) + ("log-id", "Specify id for adding context to log output", cxxopts::value<std::string>(ServerOptions.LogId)) + ("quiet", "Disable console logging", cxxopts::value<bool>(ServerOptions.NoConsoleOutput)->default_value("false")) + ("log-trace", "Change selected loggers to level TRACE", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Trace])) + ("log-debug", "Change selected loggers to level DEBUG", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Debug])) + ("log-info", "Change selected loggers to level INFO", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Info])) + ("log-warn", "Change selected loggers to level WARN", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Warn])) + ("log-error", "Change selected loggers to level ERROR", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Err])) + ("log-critical", "Change selected loggers to level CRITICAL", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Critical])) + ("log-off", "Change selected loggers to level OFF", cxxopts::value<std::string>(ServerOptions.Loggers[logging::level::Off])) + ; + // clang-format on options.add_option("security", "", @@ -952,6 +965,12 @@ ParseCliOptions(int argc, char* argv[], ZenServerOptions& ServerOptions) exit(0); } + for (int i = 0; i < logging::level::LogLevelCount; ++i) + { + logging::ConfigureLogLevels(logging::level::LogLevel(i), ServerOptions.Loggers[i]); + } + logging::RefreshLogLevels(); + ServerOptions.DataDir = MakeSafePath(DataDir); ServerOptions.BaseSnapshotDir = MakeSafePath(BaseSnapshotDir); ServerOptions.ContentDir = MakeSafePath(ContentDir); diff --git a/src/zenserver/config.h b/src/zenserver/config.h index 8135bf8f0..11311f9d8 100644 --- a/src/zenserver/config.h +++ b/src/zenserver/config.h @@ -2,6 +2,7 @@ #pragma once +#include <zencore/logbase.h> #include <zencore/zencore.h> #include <zenhttp/httpserver.h> #include <filesystem> @@ -151,6 +152,7 @@ struct ZenServerOptions bool SentryAllowPII = false; // Allow personally identifiable information in sentry crash reports bool ObjectStoreEnabled = false; bool NoConsoleOutput = false; // Control default use of stdout for diagnostics + std::string Loggers[zen::logging::level::LogLevelCount]; #if ZEN_WITH_TRACE std::string TraceHost; // Host name or IP address to send trace data to std::string TraceFile; // Path of a file to write a trace diff --git a/src/zenserver/diag/logging.cpp b/src/zenserver/diag/logging.cpp index e2d57b840..dc1675819 100644 --- a/src/zenserver/diag/logging.cpp +++ b/src/zenserver/diag/logging.cpp @@ -42,6 +42,7 @@ InitializeServerLogging(const ZenServerOptions& InOptions) /* max files */ 16, /* rotate on open */ true); auto HttpLogger = std::make_shared<spdlog::logger>("http_requests", HttpSink); + spdlog::apply_logger_env_levels(HttpLogger); spdlog::register_logger(HttpLogger); // Cache request logging @@ -53,16 +54,19 @@ InitializeServerLogging(const ZenServerOptions& InOptions) /* max files */ 16, /* rotate on open */ false); auto CacheLogger = std::make_shared<spdlog::logger>("z$", CacheSink); + spdlog::apply_logger_env_levels(CacheLogger); spdlog::register_logger(CacheLogger); // Jupiter - only log upstream HTTP traffic to file auto JupiterLogger = std::make_shared<spdlog::logger>("jupiter", FileSink); + spdlog::apply_logger_env_levels(JupiterLogger); spdlog::register_logger(JupiterLogger); // Zen - only log upstream HTTP traffic to file auto ZenClientLogger = std::make_shared<spdlog::logger>("zenclient", FileSink); + spdlog::apply_logger_env_levels(ZenClientLogger); spdlog::register_logger(ZenClientLogger); FinishInitializeLogging(LogOptions); diff --git a/src/zenutil/logging.cpp b/src/zenutil/logging.cpp index d0a6ac0b4..d82789e42 100644 --- a/src/zenutil/logging.cpp +++ b/src/zenutil/logging.cpp @@ -12,6 +12,7 @@ ZEN_THIRD_PARTY_INCLUDES_END #include <zencore/compactbinary.h> #include <zencore/filesystem.h> +#include <zencore/logging.h> #include <zencore/string.h> #include <zenutil/logging/fullformatter.h> #include <zenutil/logging/jsonformatter.h> @@ -152,21 +153,21 @@ BeginInitializeLogging(const LoggingOptions& LogOptions) void FinishInitializeLogging(const LoggingOptions& LogOptions) { - spdlog::level::level_enum LogLevel = spdlog::level::info; + logging::level::LogLevel LogLevel = logging::level::Info; if (LogOptions.IsDebug) { - LogLevel = spdlog::level::debug; + LogLevel = logging::level::Debug; } if (LogOptions.IsTest) { - LogLevel = spdlog::level::trace; + LogLevel = logging::level::Trace; } // Configure all registered loggers according to settings - spdlog::set_level(LogLevel); + logging::RefreshLogLevels(LogLevel); spdlog::flush_on(spdlog::level::err); spdlog::flush_every(std::chrono::seconds{2}); spdlog::set_formatter(std::make_unique<logging::full_formatter>(LogOptions.LogId, std::chrono::system_clock::now())); |