From 9285bbf256d2a706f1d9fb4f3b51850cfb7b904f Mon Sep 17 00:00:00 2001 From: Andre Abrantes Date: Mon, 16 Jan 2017 19:20:04 -0200 Subject: [PATCH] implementing the custom property feature with a hash map owned by the logger, including an example --- example/example.cpp | 7 +++ example/example.vcxproj | 4 +- include/spdlog/details/async_logger_impl.h | 2 +- include/spdlog/details/logger_impl.h | 10 +++- .../spdlog/details/pattern_formatter_impl.h | 53 ++++++++++++++++--- include/spdlog/details/registry.h | 4 +- include/spdlog/formatter.h | 10 ++-- include/spdlog/logger.h | 7 ++- 8 files changed, 79 insertions(+), 18 deletions(-) diff --git a/example/example.cpp b/example/example.cpp index 89a3d077..a24b5946 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -57,6 +57,13 @@ int main(int, char*[]) spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); rotating_logger->info("This is another message with custom format"); + // Using a per-logger dynamic property map + console->set_pattern("*** [%H:%M:%S %z] [thread %t] [%{property_name}] %v ***"); + auto properties = console->properties(); + (*properties)["property_name"] = "some property"; + console->info("This message has a custom property"); + (*properties)["property_name"] = "new property"; + console->info("The property has changed"); // Runtime log levels spd::set_level(spd::level::info); //Set global log level to info diff --git a/example/example.vcxproj b/example/example.vcxproj index 63db2b5d..2b8c4e55 100644 --- a/example/example.vcxproj +++ b/example/example.vcxproj @@ -56,13 +56,13 @@ Application true - v120 + v140 Unicode Application false - v120 + v140 true Unicode diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index 2092f06c..f2b371b7 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -65,7 +65,7 @@ inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_forma inline void spdlog::async_logger::_set_pattern(const std::string& pattern) { - _formatter = std::make_shared(pattern); + _formatter = std::make_shared(pattern, _properties); _async_log_helper->set_formatter(_formatter); } diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 2b27f105..4470fc59 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -18,7 +18,8 @@ template inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end): _name(logger_name), _sinks(begin, end), - _formatter(std::make_shared("%+")) + _properties(std::make_shared>()), + _formatter(std::make_shared("%+", _properties)) { _level = level::info; _flush_level = level::off; @@ -57,6 +58,11 @@ inline void spdlog::logger::set_pattern(const std::string& pattern) _set_pattern(pattern); } +inline std::shared_ptr> spdlog::logger::properties() const +{ + return _properties; +} + template inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args) @@ -259,7 +265,7 @@ inline void spdlog::logger::_sink_it(details::log_msg& msg) inline void spdlog::logger::_set_pattern(const std::string& pattern) { - _formatter = std::make_shared(pattern); + _formatter = std::make_shared(pattern, _properties); } inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter) { diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h index 3f4e9a2c..02949dec 100644 --- a/include/spdlog/details/pattern_formatter_impl.h +++ b/include/spdlog/details/pattern_formatter_impl.h @@ -396,6 +396,25 @@ private: char _ch; }; +class property_formatter:public flag_formatter +{ +public: + explicit property_formatter(std::shared_ptr> properties, const std::string& property_name) + : properties(properties), property_name(property_name) + {} + void format(details::log_msg& msg, const std::tm&) override + { + auto it = properties->find(property_name); + if (it != properties->end()) + msg.formatted << it->second; + else + msg.formatted << "null"; + } +private: + std::shared_ptr> properties; + std::string property_name; +}; + //aggregate user chars to display as is class aggregate_formatter:public flag_formatter @@ -469,7 +488,7 @@ class full_formatter:public flag_formatter /////////////////////////////////////////////////////////////////////////////// // pattern_formatter inline impl /////////////////////////////////////////////////////////////////////////////// -inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern) +inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, std::shared_ptr> properties): properties(properties) { compile_pattern(pattern); } @@ -485,10 +504,29 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter if (user_chars) //append user chars found so far _formatters.push_back(std::move(user_chars)); - if (++it != end) - handle_flag(*it); - else + if (++it == end) break; + + // the right brace must be found and the string consumed up until it + if (*it == '{') + { + auto key_start_pos = it + 1 - pattern.begin(); + auto key_end_pos = pattern.find('}', key_start_pos); + + // ignoring rest of the pattern + if (key_end_pos == pattern.size()) + break; + + auto key_length = key_end_pos - key_start_pos; + auto key = pattern.substr(key_start_pos, key_length); + handle_flag(*it, key); + + it += key_length + 1; + } + else + { + handle_flag(*it); + } } else // chars not following the % sign should be displayed as is { @@ -501,9 +539,9 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter { _formatters.push_back(std::move(user_chars)); } - } -inline void spdlog::pattern_formatter::handle_flag(char flag) + +inline void spdlog::pattern_formatter::handle_flag(char flag, const std::string& param) { switch (flag) { @@ -625,6 +663,9 @@ inline void spdlog::pattern_formatter::handle_flag(char flag) case ('P'): _formatters.push_back(std::unique_ptr(new details::pid_formatter())); break; + case ('{'): + _formatters.push_back(std::unique_ptr(new details::property_formatter(properties, param))); + break; default: //Unkown flag appears as is _formatters.push_back(std::unique_ptr(new details::ch_formatter('%'))); diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index ee14adfd..f0b87b10 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -111,9 +111,11 @@ public: void set_pattern(const std::string& pattern) { std::lock_guard lock(_mutex); - _formatter = std::make_shared(pattern); for (auto& l : _loggers) + { + _formatter = std::make_shared(pattern, l.second->properties()); l.second->set_formatter(_formatter); + } } void set_level(level::level_enum log_level) diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h index 0ffcec03..36a5df31 100644 --- a/include/spdlog/formatter.h +++ b/include/spdlog/formatter.h @@ -7,9 +7,9 @@ #include -#include -#include #include +#include +#include namespace spdlog { @@ -29,14 +29,16 @@ class pattern_formatter : public formatter { public: - explicit pattern_formatter(const std::string& pattern); + explicit pattern_formatter(const std::string& pattern, std::shared_ptr> properties); pattern_formatter(const pattern_formatter&) = delete; pattern_formatter& operator=(const pattern_formatter&) = delete; void format(details::log_msg& msg) override; private: const std::string _pattern; std::vector> _formatters; - void handle_flag(char flag); + std::shared_ptr> properties; + + void handle_flag(char flag, const std::string& param=""); void compile_pattern(const std::string& pattern); }; } diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index a2deb51d..cec94666 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -15,9 +15,9 @@ #include #include -#include #include -#include +#include +#include namespace spdlog { @@ -59,6 +59,8 @@ public: void set_pattern(const std::string&); void set_formatter(formatter_ptr); + std::shared_ptr> properties() const; + // error handler void set_error_handler(log_err_handler); log_err_handler error_handler(); @@ -83,6 +85,7 @@ protected: const std::string _name; std::vector _sinks; + std::shared_ptr> _properties; formatter_ptr _formatter; spdlog::level_t _level; spdlog::level_t _flush_level;