From 75cfffc234526ee0bc7af0b9cd93e4255a53077c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20M=C4=85ka?= Date: Thu, 12 Oct 2017 13:57:49 +0200 Subject: [PATCH] Added MDC logging feature, working only for synchronous loggers --- .../spdlog/details/pattern_formatter_impl.h | 55 ++++++++++++++++++- include/spdlog/formatter.h | 1 + include/spdlog/mdc_context_manager.h | 34 ++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 include/spdlog/mdc_context_manager.h diff --git a/include/spdlog/details/pattern_formatter_impl.h b/include/spdlog/details/pattern_formatter_impl.h index 05993e6c..f1d7e8c3 100644 --- a/include/spdlog/details/pattern_formatter_impl.h +++ b/include/spdlog/details/pattern_formatter_impl.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include namespace spdlog { @@ -425,6 +427,36 @@ private: std::string _str; }; +#define ENABLE_MDC_FORMATTER 1 + +// Disabling this feature for MinGW +// See https://github.com/Alexpux/MINGW-packages/issues/2519 +#ifdef __MINGW32__ +#undef ENABLE_MDC_FORMATTER +#define ENABLE_MDC_FORMATTER 0 +#endif + +// Enabled formatting pattern %X{key} to be mapped to appropiate value +class MDC_formatter SPDLOG_FINAL :public flag_formatter +{ +public: +#if ENABLE_MDC_FORMATTER + thread_local static std::map mdc_map; +#endif + MDC_formatter(std::string key): _key(std::move(key)) + {} + void format(details::log_msg& msg, const std::tm&) override + { +#if ENABLE_MDC_FORMATTER + msg.formatted << mdc_map[_key]; +#else + msg.formatted << "%X{" << _key << "}"; +#endif + } +private: + std::string _key; +}; + // Full info formatter // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v class full_formatter SPDLOG_FINAL:public flag_formatter @@ -496,8 +528,11 @@ 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); + if (++it != end) { + auto flag = *it; + if (flag != 'X' || !try_handle_mdc_flag(flag, it, end)) + handle_flag(flag); + } else break; } @@ -654,6 +689,22 @@ inline void spdlog::pattern_formatter::handle_flag(char flag) } } +inline bool spdlog::pattern_formatter::try_handle_mdc_flag(char flag, std::string::const_iterator& it, const std::string::const_iterator& end) +{ + if (++it != end) { + if (*it != '{') + return false; + std::smatch mdc_key_match; + auto brace_end = std::find(it, end, '}'); + if (brace_end != end && std::regex_match(it, brace_end + 1, mdc_key_match, std::regex("[{]([\\w]+)[}]"))) { + _formatters.push_back(std::unique_ptr(new details::MDC_formatter(mdc_key_match[1]))); + it += std::distance(mdc_key_match[0].first, mdc_key_match[0].second) - 1; + return true; + } + } + return false; +} + inline std::tm spdlog::pattern_formatter::get_time(details::log_msg& msg) { if (_pattern_time == pattern_time_type::local) diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h index 6bba9025..636deec0 100644 --- a/include/spdlog/formatter.h +++ b/include/spdlog/formatter.h @@ -39,6 +39,7 @@ private: std::vector> _formatters; std::tm get_time(details::log_msg& msg); void handle_flag(char flag); + bool try_handle_mdc_flag(char flag, std::string::const_iterator& it, const std::string::const_iterator& end); void compile_pattern(const std::string& pattern); }; } diff --git a/include/spdlog/mdc_context_manager.h b/include/spdlog/mdc_context_manager.h new file mode 100644 index 00000000..17802f37 --- /dev/null +++ b/include/spdlog/mdc_context_manager.h @@ -0,0 +1,34 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include "spdlog/details/pattern_formatter_impl.h" + +#include + +namespace spdlog +{ +namespace mdc +{ +inline void set_context(std::string key, std::string value) +{ +#if ENABLE_MDC_FORMATTER + spdlog::details::MDC_formatter::mdc_map[std::move(key)] = std::move(value); +#endif +} + +inline void remove_context(const std::string& key) +{ +#if ENABLE_MDC_FORMATTER + auto &mdc_map = spdlog::details::MDC_formatter::mdc_map; + auto value_it = mdc_map.find(key); + if (value_it != mdc_map.end()) + mdc_map.erase(value_it); +#endif +} +} +} +