From 1e3bf6734472569bacd9fdb803f2468d3b305bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=BE=D0=B3=D0=B8=D0=BB=D0=B8=D0=BD=20=D0=92=D0=B8?= =?UTF-8?q?=D0=BA=D1=82=D0=BE=D1=80?= Date: Wed, 18 Nov 2020 23:50:00 +0300 Subject: [PATCH] Add logger context support --- CMakeLists.txt | 2 + example/example.cpp | 41 +++++++++++++++++++ include/spdlog/details/log_msg-inl.h | 11 ++--- include/spdlog/details/log_msg.h | 7 ++-- include/spdlog/logger-inl.h | 18 ++++++--- include/spdlog/logger.h | 37 ++++++++++++++--- include/spdlog/pattern_formatter-inl.h | 19 +++++++++ include/spdlog/sinks/dup_filter_sink.h | 2 +- tests/test_daily_logger.cpp | 4 +- tests/test_dup_filter.cpp | 20 ++++----- tests/test_misc.cpp | 48 ++++++++++++++++++++++ tests/test_pattern_formatter.cpp | 56 ++++++++++++++++---------- tests/test_time_point.cpp | 2 +- 13 files changed, 213 insertions(+), 54 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b98f5509..a441f51f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.10) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + # --------------------------------------------------------------------------------------- # Start spdlog project # --------------------------------------------------------------------------------------- diff --git a/example/example.cpp b/example/example.cpp index 092eb1af..b612b255 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -20,6 +20,8 @@ void user_defined_example(); void err_handler_example(); void syslog_example(); void custom_flags_example(); +void context_example(); +void hierarchical_context_example(); #include "spdlog/spdlog.h" #include "spdlog/cfg/env.h" // for loading levels from the environment variable @@ -74,6 +76,8 @@ int main(int, char *[]) trace_example(); stopwatch_example(); custom_flags_example(); + context_example(); + hierarchical_context_example(); // Flush all *registered* loggers using a worker thread every 3 seconds. // note: registered loggers *must* be thread safe for this to work correctly! @@ -292,3 +296,40 @@ void custom_flags_example() formatter->add_flag('*').set_pattern("[%n] [%*] [%^%l%$] %v"); spdlog::set_formatter(std::move(formatter)); } + +#include "spdlog/sinks/stdout_sinks.h" +void context_example() +{ + auto logger = spdlog::stdout_logger_mt("name"); + logger->with_field("key1", "value1"); + std::string k2 = "key2"; + std::string v2 = "value2"; + logger->with_field(k2, v2); + + // the context is not printed because the flag %V is missing + logger->set_pattern("[%T] %v"); + logger->info("example without context: {}", 42); + + // the context will be printed + logger->set_pattern("[%T] [%V] %v"); + logger->info("example with context: {}", 42); + + spdlog::drop("name"); +} + +void hierarchical_context_example() +{ + auto f = [](spdlog::logger *log) + { + auto new_log = log->clone("cloned"); + new_log->with_field("key2", "val2").info("context print 2"); + }; + auto logger = spdlog::stdout_logger_mt("name"); + logger->set_pattern("[%V] %v"); + logger->with_field("key1", "value1").info("context print 1"); + f(logger.get()); + logger->info("context print 3"); + + spdlog::drop("name"); + spdlog::drop("cloned"); +} diff --git a/include/spdlog/details/log_msg-inl.h b/include/spdlog/details/log_msg-inl.h index af11e0da..4d5dd6bf 100644 --- a/include/spdlog/details/log_msg-inl.h +++ b/include/spdlog/details/log_msg-inl.h @@ -13,7 +13,7 @@ namespace spdlog { namespace details { SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::source_loc loc, string_view_t a_logger_name, - spdlog::level::level_enum lvl, spdlog::string_view_t msg) + spdlog::level::level_enum lvl, spdlog::string_view_t msg, spdlog::string_view_t ctx) : logger_name(a_logger_name) , level(lvl) , time(log_time) @@ -22,15 +22,16 @@ SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::s #endif , source(loc) , payload(msg) + , context(ctx) {} SPDLOG_INLINE log_msg::log_msg( - spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) - : log_msg(os::now(), loc, a_logger_name, lvl, msg) + spdlog::source_loc loc, string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg, spdlog::string_view_t ctx) + : log_msg(os::now(), loc, a_logger_name, lvl, msg, ctx) {} -SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg) - : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg) +SPDLOG_INLINE log_msg::log_msg(string_view_t a_logger_name, spdlog::level::level_enum lvl, spdlog::string_view_t msg, spdlog::string_view_t ctx) + : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg, ctx) {} } // namespace details diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 834ca4df..79bebc12 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -11,9 +11,9 @@ namespace details { struct SPDLOG_API log_msg { log_msg() = default; - log_msg(log_clock::time_point log_time, source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); - log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg); - log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg); + log_msg(log_clock::time_point log_time, source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg, string_view_t ctx); + log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg, string_view_t ctx); + log_msg(string_view_t logger_name, level::level_enum lvl, string_view_t msg, string_view_t ctx); log_msg(const log_msg &other) = default; string_view_t logger_name; @@ -27,6 +27,7 @@ struct SPDLOG_API log_msg source_loc source; string_view_t payload; + string_view_t context; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/logger-inl.h b/include/spdlog/logger-inl.h index d01c08da..834f6609 100644 --- a/include/spdlog/logger-inl.h +++ b/include/spdlog/logger-inl.h @@ -23,15 +23,17 @@ SPDLOG_INLINE logger::logger(const logger &other) , flush_level_(other.flush_level_.load(std::memory_order_relaxed)) , custom_err_handler_(other.custom_err_handler_) , tracer_(other.tracer_) -{} +{ + context_.append(other.context_.data(), other.context_.data() + other.context_.size()); +} SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : name_(std::move(other.name_)), sinks_(std::move(other.sinks_)), level_(other.level_.load(std::memory_order_relaxed)), flush_level_(other.flush_level_.load(std::memory_order_relaxed)), custom_err_handler_(std::move(other.custom_err_handler_)), - tracer_(std::move(other.tracer_)) - + tracer_(std::move(other.tracer_)), + context_(std::move(other.context_)) {} SPDLOG_INLINE logger &logger::operator=(logger other) SPDLOG_NOEXCEPT @@ -57,6 +59,8 @@ SPDLOG_INLINE void logger::swap(spdlog::logger &other) SPDLOG_NOEXCEPT custom_err_handler_.swap(other.custom_err_handler_); std::swap(tracer_, other.tracer_); + + std::swap(context_, other.context_); } SPDLOG_INLINE void swap(logger &a, logger &b) @@ -212,9 +216,13 @@ SPDLOG_INLINE void logger::dump_backtrace_() using details::log_msg; if (tracer_.enabled()) { - sink_it_(log_msg{name(), level::info, "****************** Backtrace Start ******************"}); + sink_it_(log_msg{name(), level::info, "****************** Backtrace Start ******************", + string_view_t(context_.data(), context_.size())}); + tracer_.foreach_pop([this](const log_msg &msg) { this->sink_it_(msg); }); - sink_it_(log_msg{name(), level::info, "****************** Backtrace End ********************"}); + + sink_it_(log_msg{name(), level::info, "****************** Backtrace End ********************", + string_view_t(context_.data(), context_.size())}); } } diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index a34c5221..1eee313e 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -152,7 +152,7 @@ public: return; } - details::log_msg log_msg(log_time, loc, name_, lvl, msg); + details::log_msg log_msg(log_time, loc, name_, lvl, msg, string_view_t(context_.data(), context_.size())); log_it_(log_msg, log_enabled, traceback_enabled); } @@ -165,7 +165,7 @@ public: return; } - details::log_msg log_msg(loc, name_, lvl, msg); + details::log_msg log_msg(loc, name_, lvl, msg, string_view_t(context_.data(), context_.size())); log_it_(log_msg, log_enabled, traceback_enabled); } @@ -241,7 +241,7 @@ public: memory_buf_t buf; details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), buf); - details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()), string_view_t(context_.data(), context_.size())); log_it_(log_msg, log_enabled, traceback_enabled); } SPDLOG_LOGGER_CATCH() @@ -262,7 +262,7 @@ public: { memory_buf_t buf; details::os::wstr_to_utf8buf(msg, buf); - details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()), string_view_t(context_.data(), context_.size())); log_it_(log_msg, log_enabled, traceback_enabled); } SPDLOG_LOGGER_CATCH() @@ -316,6 +316,32 @@ public: // create new logger with same sinks and configuration. virtual std::shared_ptr clone(std::string logger_name); + // add in context a new pair key=value + template + logger &with_field(const Key &key, const Value &value) + { + if (context_.size() > 0) + { + static const std::string space = " "; + context_.append(space.data(), space.data() + space.size()); + } + auto *buf_ptr = key.data(); + context_.append(buf_ptr, buf_ptr + key.size()); + + static const std::string eq = "="; + context_.append(eq.data(), eq.data() + eq.size()); + + buf_ptr = value.data(); + context_.append(buf_ptr, buf_ptr + value.size()); + return *this; + } + + logger &with_field(const char *key, const char *value) + { + return with_field(string_view_t(key), string_view_t(value)); + } + + protected: std::string name_; std::vector sinks_; @@ -323,6 +349,7 @@ protected: spdlog::level_t flush_level_{level::off}; err_handler custom_err_handler_{nullptr}; details::backtracer tracer_; + memory_buf_t context_; // common implementation for after templated public api has been resolved template @@ -338,7 +365,7 @@ protected: { memory_buf_t buf; fmt::format_to(buf, fmt, std::forward(args)...); - details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size())); + details::log_msg log_msg(loc, name_, lvl, string_view_t(buf.data(), buf.size()), string_view_t(context_.data(), context_.size())); log_it_(log_msg, log_enabled, traceback_enabled); } SPDLOG_LOGGER_CATCH() diff --git a/include/spdlog/pattern_formatter-inl.h b/include/spdlog/pattern_formatter-inl.h index 5a1c5eaf..ae3d1079 100644 --- a/include/spdlog/pattern_formatter-inl.h +++ b/include/spdlog/pattern_formatter-inl.h @@ -689,6 +689,21 @@ public: } }; +template +class V_formatter final : public flag_formatter +{ +public: + explicit V_formatter(padding_info padinfo) + : flag_formatter(padinfo) + {} + + void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override + { + ScopedPadder p(msg.context.size(), padinfo_, dest); + fmt_helper::append_string_view(msg.context, dest); + } +}; + class ch_formatter final : public flag_formatter { public: @@ -1097,6 +1112,10 @@ SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_i formatters_.push_back(details::make_unique>(padding)); break; + case ('V'): // the context + formatters_.push_back(details::make_unique>(padding)); + break; + case ('a'): // weekday formatters_.push_back(details::make_unique>(padding)); break; diff --git a/include/spdlog/sinks/dup_filter_sink.h b/include/spdlog/sinks/dup_filter_sink.h index c9a08d68..6495e709 100644 --- a/include/spdlog/sinks/dup_filter_sink.h +++ b/include/spdlog/sinks/dup_filter_sink.h @@ -64,7 +64,7 @@ protected: { memory_buf_t buf; fmt::format_to(buf, "Skipped {} duplicate messages..", skip_counter_); - details::log_msg skipped_msg{msg.logger_name, level::info, string_view_t{buf.data(), buf.size()}}; + details::log_msg skipped_msg{msg.logger_name, level::info, string_view_t{buf.data(), buf.size()}, msg.context}; dist_sink::sink_it_(skipped_msg); } diff --git a/tests/test_daily_logger.cpp b/tests/test_daily_logger.cpp index a3e70e68..b4085843 100644 --- a/tests/test_daily_logger.cpp +++ b/tests/test_daily_logger.cpp @@ -103,7 +103,7 @@ TEST_CASE("daily_file_sink::daily_filename_calculator", "[daily_file_sink]]") static spdlog::details::log_msg create_msg(std::chrono::seconds offset) { using spdlog::log_clock; - spdlog::details::log_msg msg{"test", spdlog::level::info, "Hello Message"}; + spdlog::details::log_msg msg{"test", spdlog::level::info, "Hello Message", ""}; msg.time = log_clock::now() + offset; return msg; } @@ -146,4 +146,4 @@ TEST_CASE("daily_logger rotate", "[daily_file_sink]") test_rotate(days_to_run, 10, 10); test_rotate(days_to_run, 11, 10); test_rotate(days_to_run, 20, 10); -} \ No newline at end of file +} diff --git a/tests/test_dup_filter.cpp b/tests/test_dup_filter.cpp index 795278a0..740324d5 100644 --- a/tests/test_dup_filter.cpp +++ b/tests/test_dup_filter.cpp @@ -13,7 +13,7 @@ TEST_CASE("dup_filter_test1", "[dup_filter_sink]") for (int i = 0; i < 10; i++) { - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1"}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1", ""}); } REQUIRE(test_sink->msg_counter() == 1); @@ -30,7 +30,7 @@ TEST_CASE("dup_filter_test2", "[dup_filter_sink]") for (int i = 0; i < 10; i++) { - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1"}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1", ""}); std::this_thread::sleep_for(std::chrono::milliseconds(5)); } @@ -48,8 +48,8 @@ TEST_CASE("dup_filter_test3", "[dup_filter_sink]") for (int i = 0; i < 10; i++) { - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1"}); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message2"}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1", ""}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message2", ""}); } REQUIRE(test_sink->msg_counter() == 20); @@ -64,9 +64,9 @@ TEST_CASE("dup_filter_test4", "[dup_filter_sink]") auto test_sink = std::make_shared(); dup_sink.add_sink(test_sink); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message"}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message", ""}); std::this_thread::sleep_for(std::chrono::milliseconds(50)); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message"}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message", ""}); REQUIRE(test_sink->msg_counter() == 2); } @@ -79,10 +79,10 @@ TEST_CASE("dup_filter_test5", "[dup_filter_sink]") auto test_sink = std::make_shared(); dup_sink.add_sink(test_sink); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1"}); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1"}); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1"}); - dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message2"}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1", ""}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1", ""}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message1", ""}); + dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message2", ""}); REQUIRE(test_sink->msg_counter() == 3); // skip 2 messages but log the "skipped.." message before message2 } diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index 1d67e879..ec69b05e 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -114,6 +114,54 @@ TEST_CASE("clone-logger", "[clone]") spdlog::drop_all(); } +TEST_CASE("clone-logger-with-context", "[clone]") +{ + using spdlog::sinks::test_sink_mt; + auto test_sink = std::make_shared(); + auto logger = std::make_shared("orig", test_sink); + logger->with_field("key", "value"); + logger->set_pattern("[%V] %v"); + auto cloned = logger->clone("clone"); + + REQUIRE(cloned->name() == "clone"); + REQUIRE(logger->sinks() == cloned->sinks()); + REQUIRE(logger->level() == cloned->level()); + REQUIRE(logger->flush_level() == cloned->flush_level()); + logger->info("Some message 1"); + cloned->info("Some message 2"); + + REQUIRE(test_sink->lines().size() == 2); + REQUIRE(test_sink->lines()[0] == "[key=value] Some message 1"); + REQUIRE(test_sink->lines()[1] == "[key=value] Some message 2"); + + spdlog::drop_all(); +} + +TEST_CASE("clone-logger-modify-context", "[clone]") +{ + using spdlog::sinks::test_sink_mt; + auto test_sink = std::make_shared(); + auto logger = std::make_shared("orig", test_sink); + logger->set_pattern("[%V] %v"); + logger->with_field("key1", "val1"); + + auto cloned = logger->clone("clone"); + cloned->with_field("key2", "val2"); + + REQUIRE(cloned->name() == "clone"); + REQUIRE(logger->sinks() == cloned->sinks()); + REQUIRE(logger->level() == cloned->level()); + REQUIRE(logger->flush_level() == cloned->flush_level()); + logger->info("Some message 1"); + cloned->info("Some message 2"); + + REQUIRE(test_sink->lines().size() == 2); + REQUIRE(test_sink->lines()[0] == "[key1=val1] Some message 1"); + REQUIRE(test_sink->lines()[1] == "[key1=val1 key2=val2] Some message 2"); + + spdlog::drop_all(); +} + TEST_CASE("clone async", "[clone]") { using spdlog::sinks::test_sink_st; diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index 3efe1c44..e8d87958 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -67,7 +67,7 @@ TEST_CASE("color range test1", "[pattern_formatter]") fmt::format_to(buf, "Hello"); memory_buf_t formatted; std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, spdlog::string_view_t(buf.data(), buf.size())); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, spdlog::string_view_t(buf.data(), buf.size()), ""); formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_end == 5); @@ -78,7 +78,7 @@ TEST_CASE("color range test2", "[pattern_formatter]") { auto formatter = std::make_shared("%^%$", spdlog::pattern_time_type::local, "\n"); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, ""); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "", ""); memory_buf_t formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); @@ -90,7 +90,7 @@ TEST_CASE("color range test3", "[pattern_formatter]") { auto formatter = std::make_shared("%^***%$"); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored", ""); memory_buf_t formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); @@ -101,7 +101,7 @@ TEST_CASE("color range test4", "[pattern_formatter]") { auto formatter = std::make_shared("XX%^YYY%$", spdlog::pattern_time_type::local, "\n"); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored", ""); memory_buf_t formatted; formatter->format(msg, formatted); @@ -114,7 +114,7 @@ TEST_CASE("color range test5", "[pattern_formatter]") { auto formatter = std::make_shared("**%^"); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored", ""); memory_buf_t formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 2); @@ -125,7 +125,7 @@ TEST_CASE("color range test6", "[pattern_formatter]") { auto formatter = std::make_shared("**%$"); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored", ""); memory_buf_t formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); @@ -235,11 +235,11 @@ TEST_CASE("padding_truncate_funcname", "[pattern_formatter]") auto formatter = std::unique_ptr(new spdlog::pattern_formatter(pattern)); test_sink.set_formatter(std::move(formatter)); - spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message"}; + spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message", ""}; test_sink.log(msg1); REQUIRE(test_sink.lines()[0] == "message [ func]"); - spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "function"}, "test_logger", spdlog::level::info, "message"}; + spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "function"}, "test_logger", spdlog::level::info, "message", ""}; test_sink.log(msg2); REQUIRE(test_sink.lines()[1] == "message [funct]"); } @@ -252,11 +252,11 @@ TEST_CASE("padding_funcname", "[pattern_formatter]") auto formatter = std::unique_ptr(new spdlog::pattern_formatter(pattern)); test_sink.set_formatter(std::move(formatter)); - spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message"}; + spdlog::details::log_msg msg1{spdlog::source_loc{"ignored", 1, "func"}, "test_logger", spdlog::level::info, "message", ""}; test_sink.log(msg1); REQUIRE(test_sink.lines()[0] == "message [ func]"); - spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "func567890123"}, "test_logger", spdlog::level::info, "message"}; + spdlog::details::log_msg msg2{spdlog::source_loc{"ignored", 1, "func567890123"}, "test_logger", spdlog::level::info, "message", ""}; test_sink.log(msg2); REQUIRE(test_sink.lines()[1] == "message [func567890123]"); } @@ -266,7 +266,7 @@ TEST_CASE("clone-default-formatter", "[pattern_formatter]") auto formatter_1 = std::make_shared(); auto formatter_2 = formatter_1->clone(); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message", ""); memory_buf_t formatted_1; memory_buf_t formatted_2; @@ -281,7 +281,7 @@ TEST_CASE("clone-default-formatter2", "[pattern_formatter]") auto formatter_1 = std::make_shared("%+"); auto formatter_2 = formatter_1->clone(); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message", ""); memory_buf_t formatted_1; memory_buf_t formatted_2; @@ -296,7 +296,7 @@ TEST_CASE("clone-formatter", "[pattern_formatter]") auto formatter_1 = std::make_shared("%D %X [%] [%n] %v"); auto formatter_2 = formatter_1->clone(); std::string logger_name = "test"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message", ""); memory_buf_t formatted_1; memory_buf_t formatted_2; @@ -311,7 +311,7 @@ TEST_CASE("clone-formatter-2", "[pattern_formatter]") auto formatter_1 = std::make_shared("%D %X [%] [%n] %v", pattern_time_type::utc, "xxxxxx\n"); auto formatter_2 = formatter_1->clone(); std::string logger_name = "test2"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message", ""); memory_buf_t formatted_1; memory_buf_t formatted_2; @@ -355,7 +355,7 @@ TEST_CASE("clone-custom_formatter", "[pattern_formatter]") formatter_1->add_flag('t', "custom_output").set_pattern("[%n] [%t] %v"); auto formatter_2 = formatter_1->clone(); std::string logger_name = "logger-name"; - spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message"); + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "some message", ""); memory_buf_t formatted_1; memory_buf_t formatted_2; @@ -383,7 +383,7 @@ TEST_CASE("short filename formatter-1", "[pattern_formatter]") memory_buf_t formatted; std::string logger_name = "logger-name"; spdlog::source_loc source_loc{test_path, 123, "some_func()"}; - spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello"); + spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello", ""); formatter.format(msg, formatted); REQUIRE(fmt::to_string(formatted) == "myfile.cpp"); } @@ -394,7 +394,7 @@ TEST_CASE("short filename formatter-2", "[pattern_formatter]") memory_buf_t formatted; std::string logger_name = "logger-name"; spdlog::source_loc source_loc{"myfile.cpp", 123, "some_func()"}; - spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello"); + spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello", ""); formatter.format(msg, formatted); REQUIRE(fmt::to_string(formatted) == "myfile.cpp:123"); } @@ -405,7 +405,7 @@ TEST_CASE("short filename formatter-3", "[pattern_formatter]") memory_buf_t formatted; std::string logger_name = "logger-name"; spdlog::source_loc source_loc{"", 123, "some_func()"}; - spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello"); + spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello", ""); formatter.format(msg, formatted); REQUIRE(fmt::to_string(formatted) == " Hello"); } @@ -416,7 +416,7 @@ TEST_CASE("full filename formatter", "[pattern_formatter]") memory_buf_t formatted; std::string logger_name = "logger-name"; spdlog::source_loc source_loc{test_path, 123, "some_func()"}; - spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello"); + spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello", ""); formatter.format(msg, formatted); REQUIRE(fmt::to_string(formatted) == test_path); } @@ -428,7 +428,7 @@ TEST_CASE("custom flags", "[pattern_formatter]") memory_buf_t formatted; - spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message"); + spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message", ""); formatter->format(msg, formatted); auto expected = fmt::format("[logger-name] [custom1] [custom2] some message{}", spdlog::details::os::default_eol); REQUIRE(fmt::to_string(formatted) == expected); @@ -441,7 +441,7 @@ TEST_CASE("custom flags-padding", "[pattern_formatter]") memory_buf_t formatted; - spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message"); + spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message", ""); formatter->format(msg, formatted); auto expected = fmt::format("[logger-name] [custom1] [ custom2] some message{}", spdlog::details::os::default_eol); REQUIRE(fmt::to_string(formatted) == expected); @@ -453,6 +453,18 @@ TEST_CASE("custom flags-exception", "[pattern_formatter]") formatter->add_flag('t', "throw_me").add_flag('u', "custom2").set_pattern("[%n] [%t] [%u] %v"); memory_buf_t formatted; - spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message"); + spdlog::details::log_msg msg(spdlog::source_loc{}, "logger-name", spdlog::level::info, "some message", ""); CHECK_THROWS_AS(formatter->format(msg, formatted), spdlog::spdlog_ex); } + +TEST_CASE("log with context", "[pattern_formatter]") +{ + spdlog::pattern_formatter formatter("[%V] %v", spdlog::pattern_time_type::local, ""); + memory_buf_t formatted; + std::string logger_name = "logger-name"; + spdlog::source_loc source_loc{"", 123, "some_func()"}; + spdlog::details::log_msg msg(source_loc, "logger-name", spdlog::level::info, "Hello", "key1=val1"); + formatter.format(msg, formatted); + REQUIRE(fmt::to_string(formatted) == "[key1=val1] Hello"); +} + diff --git a/tests/test_time_point.cpp b/tests/test_time_point.cpp index bacff69a..96647461 100644 --- a/tests/test_time_point.cpp +++ b/tests/test_time_point.cpp @@ -15,7 +15,7 @@ TEST_CASE("time_point1", "[time_point log_msg]") test_sink->set_delay(std::chrono::milliseconds(10)); for (int i = 0; i < 5; i++) { - spdlog::details::log_msg msg{tp, source, "test_logger", spdlog::level::info, "message"}; + spdlog::details::log_msg msg{tp, source, "test_logger", spdlog::level::info, "message", ""}; test_sink->log(msg); }