diff --git a/example/example.cpp b/example/example.cpp index fec6b0b4..11af5b6c 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -6,13 +6,18 @@ #include #include +#include int main(int, char *[]) { try { - spdlog::env::init(); - spdlog::info("Hello"); + spdlog::env::load_levels(); + auto l1 = spdlog::stderr_color_st("l1"); + auto l2 = spdlog::stderr_color_st("l2"); + spdlog::info("Hello default logger"); + l1->debug("Hello l1"); + l2->trace("Hello l2"); } catch (spdlog::spdlog_ex &ex) { diff --git a/include/spdlog/cfg/env-inl.h b/include/spdlog/cfg/env-inl.h index 7fdd23d4..46fbe34a 100644 --- a/include/spdlog/cfg/env-inl.h +++ b/include/spdlog/cfg/env-inl.h @@ -4,12 +4,12 @@ #pragma once #ifndef SPDLOG_HEADER_ONLY -#include "spdlog/cfg/env.h" +#include #endif -#include "spdlog/spdlog.h" -#include "spdlog/details/os.h" -#include "spdlog/details/registry.h" +#include +#include +#include #include #include @@ -74,73 +74,43 @@ SPDLOG_INLINE std::unordered_map extract_key_vals_(con continue; } auto kv = extract_kv_('=', token); - - // '*' marks all loggers - if (kv.first.empty()) - { - kv.first = "*"; - } - rv.insert(std::move(kv)); + rv[kv.first] = kv.second; } return rv; } -inline details::registry::logger_cfgs from_env_() +inline details::registry::logger_levels from_env_() { using details::os::getenv; - details::registry::logger_cfgs configs; + auto key_vals = extract_key_vals_(getenv("SPDLOG_LEVEL")); + details::registry::logger_levels rv; - auto levels = extract_key_vals_(getenv("SPDLOG_LEVEL")); - auto patterns = extract_key_vals_(getenv("SPDLOG_PATTERN")); - - // merge to single dict. and take into account "*" - for (auto &name_level : levels) + for (auto &name_level : key_vals) { auto &logger_name = name_level.first; - assert(!logger_name.empty()); auto level_name = to_lower_(name_level.second); - details::registry::logger_cfg cfg; - cfg.level_name = level_name; - if (logger_name == "*") + auto level = level::from_str(level_name); + // fallback to "info" if unrecognized level name + if (level == level::off && level_name != "off") { - configs.default_cfg.level_name = cfg.level_name; + level = level::info; + } + + if (logger_name.empty() || logger_name == "*") + { + rv.default_level = level; } else { - configs.loggers.emplace(logger_name, cfg); - } - - } - - for (auto &name_pattern : patterns) - { - auto &logger_name = name_pattern.first; - auto &pattern = name_pattern.second; - auto it = configs.loggers.find(logger_name); - - if (it != configs.loggers.end()) - { - it->second.pattern = pattern; - } - - if (logger_name == "*") - { - configs.default_cfg.pattern = pattern; - } - else - { - details::registry::logger_cfg cfg; - cfg.pattern = pattern; - configs.loggers.emplace(logger_name, cfg); + rv.levels[logger_name] = level; } } - - return configs; + return rv; } -SPDLOG_INLINE void init() +SPDLOG_INLINE void load_levels() { - spdlog::details::registry::instance().set_configs(from_env_()); + spdlog::details::registry::instance().set_levels(from_env_()); } } // namespace env diff --git a/include/spdlog/cfg/env.h b/include/spdlog/cfg/env.h index 7402ed2f..83336c2c 100644 --- a/include/spdlog/cfg/env.h +++ b/include/spdlog/cfg/env.h @@ -8,8 +8,9 @@ #include // -// Init levels and patterns from env variables SPDLOG_LEVEL and SPDLOG_PATTERN. +// Init levels and patterns from env variables SPDLOG_LEVEL // Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger). +// Note - fallback to "info" level on unrecognized levels // // Examples: // @@ -21,19 +22,10 @@ // // turn off all logging except for logger1 and logger2: // export SPDLOG_LEVEL="off,logger1=debug,logger2=info" -// -// set global pattern: -// export SPDLOG_PATTERN="[%x] [%l] [%n] %v" -// -// set pattern for logger1: -// export SPDLOG_PATTERN="logger1=%v,*=[%x] [%l] [%n] %v" -// -// set global pattern and different pattern for logger1: -// export SPDLOG_PATTERN="[%x] [%l] [%n] %v,logger1=[%u] %v" namespace spdlog { namespace env { -void init(); +void load_levels(); } } // namespace spdlog diff --git a/include/spdlog/details/registry-inl.h b/include/spdlog/details/registry-inl.h index 912c1237..7d4fa746 100644 --- a/include/spdlog/details/registry-inl.h +++ b/include/spdlog/details/registry-inl.h @@ -30,6 +30,12 @@ namespace spdlog { namespace details { +SPDLOG_INLINE level::level_enum registry::logger_levels::get_or_default(const std::string &name) +{ + auto it = levels.find(name); + return it != levels.end() ? it->second : default_level; +} + SPDLOG_INLINE registry::registry() : formatter_(new pattern_formatter()) { @@ -64,7 +70,7 @@ SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr new_logge new_logger->set_error_handler(err_handler_); } - new_logger->set_level(level_); + new_logger->set_level(levels_.get_or_default(new_logger->name())); new_logger->flush_on(flush_level_); if (backtrace_n_messages_ > 0) @@ -168,7 +174,7 @@ SPDLOG_INLINE void registry::set_level(level::level_enum log_level) { l.second->set_level(log_level); } - level_ = log_level; + levels_.default_level = log_level; } SPDLOG_INLINE void registry::flush_on(level::level_enum log_level) @@ -260,23 +266,15 @@ SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registrat automatic_registration_ = automatic_registration; } - -SPDLOG_INLINE void registry::set_configs(logger_cfgs configs) +SPDLOG_INLINE void registry::set_levels(logger_levels levels) { std::lock_guard lock(logger_map_mutex_); + levels_ = std::move(levels); for (auto &l : loggers_) { auto &logger = l.second; - auto cfg_it = configs.loggers.find(logger->name()); - - // use default config if not found for this logger name - logger_cfg *cfg = cfg_it != configs.loggers.end() ? &cfg_it->second : &configs.default_cfg; - auto &level_name = cfg->level_name.empty() ? cfg->level_name: configs.default_cfg.level_name; - auto &pattern = cfg->pattern.empty() ? cfg->pattern: configs.default_cfg.pattern; - logger->set_level(level::from_str(level_name)); - logger->set_formatter(details::make_unique(pattern)); + logger->set_level(levels_.get_or_default(logger->name())); } - logger_cfgs_ = std::move(configs); } SPDLOG_INLINE registry ®istry::instance() @@ -299,5 +297,6 @@ SPDLOG_INLINE void registry::register_logger_(std::shared_ptr new_logger throw_if_exists_(logger_name); loggers_[logger_name] = std::move(new_logger); } + } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 82093534..4590c5b8 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -27,16 +27,11 @@ class periodic_worker; class registry { public: - struct logger_cfg + struct logger_levels { - std::string level_name; - std::string pattern; - }; - - struct logger_cfgs - { - std::unordered_map loggers; - logger_cfg default_cfg = {"info", "%+"}; + std::unordered_map levels; + spdlog::level::level_enum default_level = level::info; + spdlog::level::level_enum get_or_default(const std::string &name); }; registry(const registry &) = delete; @@ -91,7 +86,7 @@ public: void set_automatic_registration(bool automatic_registration); - void set_configs(logger_cfgs configs); + void set_levels(logger_levels levels); static registry &instance(); @@ -104,15 +99,14 @@ private: std::mutex logger_map_mutex_, flusher_mutex_; std::recursive_mutex tp_mutex_; std::unordered_map> loggers_; + logger_levels levels_; std::unique_ptr formatter_; - level::level_enum level_ = level::info; level::level_enum flush_level_ = level::off; void (*err_handler_)(const std::string &msg); std::shared_ptr tp_; std::unique_ptr periodic_flusher_; std::shared_ptr default_logger_; bool automatic_registration_ = true; - logger_cfgs logger_cfgs_; size_t backtrace_n_messages_ = 0; };