Add logger context support

pull/1740/head
Могилин Виктор 5 years ago
parent eebb921c9f
commit 1e3bf67344

@ -2,6 +2,8 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------
# Start spdlog project # Start spdlog project
# --------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------

@ -20,6 +20,8 @@ void user_defined_example();
void err_handler_example(); void err_handler_example();
void syslog_example(); void syslog_example();
void custom_flags_example(); void custom_flags_example();
void context_example();
void hierarchical_context_example();
#include "spdlog/spdlog.h" #include "spdlog/spdlog.h"
#include "spdlog/cfg/env.h" // for loading levels from the environment variable #include "spdlog/cfg/env.h" // for loading levels from the environment variable
@ -74,6 +76,8 @@ int main(int, char *[])
trace_example(); trace_example();
stopwatch_example(); stopwatch_example();
custom_flags_example(); custom_flags_example();
context_example();
hierarchical_context_example();
// Flush all *registered* loggers using a worker thread every 3 seconds. // Flush all *registered* loggers using a worker thread every 3 seconds.
// note: registered loggers *must* be thread safe for this to work correctly! // note: registered loggers *must* be thread safe for this to work correctly!
@ -292,3 +296,40 @@ void custom_flags_example()
formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v"); formatter->add_flag<my_formatter_flag>('*').set_pattern("[%n] [%*] [%^%l%$] %v");
spdlog::set_formatter(std::move(formatter)); 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");
}

@ -13,7 +13,7 @@ namespace spdlog {
namespace details { 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_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) : logger_name(a_logger_name)
, level(lvl) , level(lvl)
, time(log_time) , time(log_time)
@ -22,15 +22,16 @@ SPDLOG_INLINE log_msg::log_msg(spdlog::log_clock::time_point log_time, spdlog::s
#endif #endif
, source(loc) , source(loc)
, payload(msg) , payload(msg)
, context(ctx)
{} {}
SPDLOG_INLINE log_msg::log_msg( 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) 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) : 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) 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) : log_msg(os::now(), source_loc{}, a_logger_name, lvl, msg, ctx)
{} {}
} // namespace details } // namespace details

@ -11,9 +11,9 @@ namespace details {
struct SPDLOG_API log_msg struct SPDLOG_API log_msg
{ {
log_msg() = default; 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(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); 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); 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; log_msg(const log_msg &other) = default;
string_view_t logger_name; string_view_t logger_name;
@ -27,6 +27,7 @@ struct SPDLOG_API log_msg
source_loc source; source_loc source;
string_view_t payload; string_view_t payload;
string_view_t context;
}; };
} // namespace details } // namespace details
} // namespace spdlog } // namespace spdlog

@ -23,15 +23,17 @@ SPDLOG_INLINE logger::logger(const logger &other)
, flush_level_(other.flush_level_.load(std::memory_order_relaxed)) , flush_level_(other.flush_level_.load(std::memory_order_relaxed))
, custom_err_handler_(other.custom_err_handler_) , custom_err_handler_(other.custom_err_handler_)
, tracer_(other.tracer_) , 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_)), SPDLOG_INLINE logger::logger(logger &&other) SPDLOG_NOEXCEPT : name_(std::move(other.name_)),
sinks_(std::move(other.sinks_)), sinks_(std::move(other.sinks_)),
level_(other.level_.load(std::memory_order_relaxed)), level_(other.level_.load(std::memory_order_relaxed)),
flush_level_(other.flush_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_)), 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 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_); custom_err_handler_.swap(other.custom_err_handler_);
std::swap(tracer_, other.tracer_); std::swap(tracer_, other.tracer_);
std::swap(context_, other.context_);
} }
SPDLOG_INLINE void swap(logger &a, logger &b) SPDLOG_INLINE void swap(logger &a, logger &b)
@ -212,9 +216,13 @@ SPDLOG_INLINE void logger::dump_backtrace_()
using details::log_msg; using details::log_msg;
if (tracer_.enabled()) 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); }); 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())});
} }
} }

@ -152,7 +152,7 @@ public:
return; 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); log_it_(log_msg, log_enabled, traceback_enabled);
} }
@ -165,7 +165,7 @@ public:
return; 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); log_it_(log_msg, log_enabled, traceback_enabled);
} }
@ -241,7 +241,7 @@ public:
memory_buf_t buf; memory_buf_t buf;
details::os::wstr_to_utf8buf(wstring_view_t(wbuf.data(), wbuf.size()), 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); log_it_(log_msg, log_enabled, traceback_enabled);
} }
SPDLOG_LOGGER_CATCH() SPDLOG_LOGGER_CATCH()
@ -262,7 +262,7 @@ public:
{ {
memory_buf_t buf; memory_buf_t buf;
details::os::wstr_to_utf8buf(msg, 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); log_it_(log_msg, log_enabled, traceback_enabled);
} }
SPDLOG_LOGGER_CATCH() SPDLOG_LOGGER_CATCH()
@ -316,6 +316,32 @@ public:
// create new logger with same sinks and configuration. // create new logger with same sinks and configuration.
virtual std::shared_ptr<logger> clone(std::string logger_name); virtual std::shared_ptr<logger> clone(std::string logger_name);
// add in context a new pair key=value
template <typename Key, typename Value>
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: protected:
std::string name_; std::string name_;
std::vector<sink_ptr> sinks_; std::vector<sink_ptr> sinks_;
@ -323,6 +349,7 @@ protected:
spdlog::level_t flush_level_{level::off}; spdlog::level_t flush_level_{level::off};
err_handler custom_err_handler_{nullptr}; err_handler custom_err_handler_{nullptr};
details::backtracer tracer_; details::backtracer tracer_;
memory_buf_t context_;
// common implementation for after templated public api has been resolved // common implementation for after templated public api has been resolved
template<typename FormatString, typename... Args> template<typename FormatString, typename... Args>
@ -338,7 +365,7 @@ protected:
{ {
memory_buf_t buf; memory_buf_t buf;
fmt::format_to(buf, fmt, std::forward<Args>(args)...); fmt::format_to(buf, fmt, std::forward<Args>(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); log_it_(log_msg, log_enabled, traceback_enabled);
} }
SPDLOG_LOGGER_CATCH() SPDLOG_LOGGER_CATCH()

@ -689,6 +689,21 @@ public:
} }
}; };
template<typename ScopedPadder>
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 class ch_formatter final : public flag_formatter
{ {
public: public:
@ -1097,6 +1112,10 @@ SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_i
formatters_.push_back(details::make_unique<details::v_formatter<Padder>>(padding)); formatters_.push_back(details::make_unique<details::v_formatter<Padder>>(padding));
break; break;
case ('V'): // the context
formatters_.push_back(details::make_unique<details::V_formatter<Padder>>(padding));
break;
case ('a'): // weekday case ('a'): // weekday
formatters_.push_back(details::make_unique<details::a_formatter<Padder>>(padding)); formatters_.push_back(details::make_unique<details::a_formatter<Padder>>(padding));
break; break;

@ -64,7 +64,7 @@ protected:
{ {
memory_buf_t buf; memory_buf_t buf;
fmt::format_to(buf, "Skipped {} duplicate messages..", skip_counter_); 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<Mutex>::sink_it_(skipped_msg); dist_sink<Mutex>::sink_it_(skipped_msg);
} }

@ -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) static spdlog::details::log_msg create_msg(std::chrono::seconds offset)
{ {
using spdlog::log_clock; 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; msg.time = log_clock::now() + offset;
return msg; 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, 10, 10);
test_rotate(days_to_run, 11, 10); test_rotate(days_to_run, 11, 10);
test_rotate(days_to_run, 20, 10); test_rotate(days_to_run, 20, 10);
} }

@ -13,7 +13,7 @@ TEST_CASE("dup_filter_test1", "[dup_filter_sink]")
for (int i = 0; i < 10; i++) 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); 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++) 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)); 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++) 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", ""});
dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message2"}); dup_sink.log(spdlog::details::log_msg{"test", spdlog::level::info, "message2", ""});
} }
REQUIRE(test_sink->msg_counter() == 20); REQUIRE(test_sink->msg_counter() == 20);
@ -64,9 +64,9 @@ TEST_CASE("dup_filter_test4", "[dup_filter_sink]")
auto test_sink = std::make_shared<test_sink_mt>(); auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink); 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)); 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); REQUIRE(test_sink->msg_counter() == 2);
} }
@ -79,10 +79,10 @@ TEST_CASE("dup_filter_test5", "[dup_filter_sink]")
auto test_sink = std::make_shared<test_sink_mt>(); auto test_sink = std::make_shared<test_sink_mt>();
dup_sink.add_sink(test_sink); 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, "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, "message2", ""});
REQUIRE(test_sink->msg_counter() == 3); // skip 2 messages but log the "skipped.." message before message2 REQUIRE(test_sink->msg_counter() == 3); // skip 2 messages but log the "skipped.." message before message2
} }

@ -114,6 +114,54 @@ TEST_CASE("clone-logger", "[clone]")
spdlog::drop_all(); spdlog::drop_all();
} }
TEST_CASE("clone-logger-with-context", "[clone]")
{
using spdlog::sinks::test_sink_mt;
auto test_sink = std::make_shared<test_sink_mt>();
auto logger = std::make_shared<spdlog::logger>("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<test_sink_mt>();
auto logger = std::make_shared<spdlog::logger>("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]") TEST_CASE("clone async", "[clone]")
{ {
using spdlog::sinks::test_sink_st; using spdlog::sinks::test_sink_st;

@ -67,7 +67,7 @@ TEST_CASE("color range test1", "[pattern_formatter]")
fmt::format_to(buf, "Hello"); fmt::format_to(buf, "Hello");
memory_buf_t formatted; memory_buf_t formatted;
std::string logger_name = "test"; 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); formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_start == 0);
REQUIRE(msg.color_range_end == 5); REQUIRE(msg.color_range_end == 5);
@ -78,7 +78,7 @@ TEST_CASE("color range test2", "[pattern_formatter]")
{ {
auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%$", spdlog::pattern_time_type::local, "\n"); auto formatter = std::make_shared<spdlog::pattern_formatter>("%^%$", spdlog::pattern_time_type::local, "\n");
std::string logger_name = "test"; 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; memory_buf_t formatted;
formatter->format(msg, formatted); formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_start == 0);
@ -90,7 +90,7 @@ TEST_CASE("color range test3", "[pattern_formatter]")
{ {
auto formatter = std::make_shared<spdlog::pattern_formatter>("%^***%$"); auto formatter = std::make_shared<spdlog::pattern_formatter>("%^***%$");
std::string logger_name = "test"; 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; memory_buf_t formatted;
formatter->format(msg, formatted); formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_start == 0);
@ -101,7 +101,7 @@ TEST_CASE("color range test4", "[pattern_formatter]")
{ {
auto formatter = std::make_shared<spdlog::pattern_formatter>("XX%^YYY%$", spdlog::pattern_time_type::local, "\n"); auto formatter = std::make_shared<spdlog::pattern_formatter>("XX%^YYY%$", spdlog::pattern_time_type::local, "\n");
std::string logger_name = "test"; 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; memory_buf_t formatted;
formatter->format(msg, formatted); formatter->format(msg, formatted);
@ -114,7 +114,7 @@ TEST_CASE("color range test5", "[pattern_formatter]")
{ {
auto formatter = std::make_shared<spdlog::pattern_formatter>("**%^"); auto formatter = std::make_shared<spdlog::pattern_formatter>("**%^");
std::string logger_name = "test"; 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; memory_buf_t formatted;
formatter->format(msg, formatted); formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 2); REQUIRE(msg.color_range_start == 2);
@ -125,7 +125,7 @@ TEST_CASE("color range test6", "[pattern_formatter]")
{ {
auto formatter = std::make_shared<spdlog::pattern_formatter>("**%$"); auto formatter = std::make_shared<spdlog::pattern_formatter>("**%$");
std::string logger_name = "test"; 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; memory_buf_t formatted;
formatter->format(msg, formatted); formatter->format(msg, formatted);
REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_start == 0);
@ -235,11 +235,11 @@ TEST_CASE("padding_truncate_funcname", "[pattern_formatter]")
auto formatter = std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter(pattern)); auto formatter = std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter(pattern));
test_sink.set_formatter(std::move(formatter)); 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); test_sink.log(msg1);
REQUIRE(test_sink.lines()[0] == "message [ func]"); 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); test_sink.log(msg2);
REQUIRE(test_sink.lines()[1] == "message [funct]"); REQUIRE(test_sink.lines()[1] == "message [funct]");
} }
@ -252,11 +252,11 @@ TEST_CASE("padding_funcname", "[pattern_formatter]")
auto formatter = std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter(pattern)); auto formatter = std::unique_ptr<spdlog::formatter>(new spdlog::pattern_formatter(pattern));
test_sink.set_formatter(std::move(formatter)); 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); test_sink.log(msg1);
REQUIRE(test_sink.lines()[0] == "message [ func]"); 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); test_sink.log(msg2);
REQUIRE(test_sink.lines()[1] == "message [func567890123]"); REQUIRE(test_sink.lines()[1] == "message [func567890123]");
} }
@ -266,7 +266,7 @@ TEST_CASE("clone-default-formatter", "[pattern_formatter]")
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>(); auto formatter_1 = std::make_shared<spdlog::pattern_formatter>();
auto formatter_2 = formatter_1->clone(); auto formatter_2 = formatter_1->clone();
std::string logger_name = "test"; 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_1;
memory_buf_t formatted_2; memory_buf_t formatted_2;
@ -281,7 +281,7 @@ TEST_CASE("clone-default-formatter2", "[pattern_formatter]")
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%+"); auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%+");
auto formatter_2 = formatter_1->clone(); auto formatter_2 = formatter_1->clone();
std::string logger_name = "test"; 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_1;
memory_buf_t formatted_2; memory_buf_t formatted_2;
@ -296,7 +296,7 @@ TEST_CASE("clone-formatter", "[pattern_formatter]")
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v"); auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v");
auto formatter_2 = formatter_1->clone(); auto formatter_2 = formatter_1->clone();
std::string logger_name = "test"; 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_1;
memory_buf_t formatted_2; memory_buf_t formatted_2;
@ -311,7 +311,7 @@ TEST_CASE("clone-formatter-2", "[pattern_formatter]")
auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v", pattern_time_type::utc, "xxxxxx\n"); auto formatter_1 = std::make_shared<spdlog::pattern_formatter>("%D %X [%] [%n] %v", pattern_time_type::utc, "xxxxxx\n");
auto formatter_2 = formatter_1->clone(); auto formatter_2 = formatter_1->clone();
std::string logger_name = "test2"; 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_1;
memory_buf_t formatted_2; memory_buf_t formatted_2;
@ -355,7 +355,7 @@ TEST_CASE("clone-custom_formatter", "[pattern_formatter]")
formatter_1->add_flag<custom_test_flag>('t', "custom_output").set_pattern("[%n] [%t] %v"); formatter_1->add_flag<custom_test_flag>('t', "custom_output").set_pattern("[%n] [%t] %v");
auto formatter_2 = formatter_1->clone(); auto formatter_2 = formatter_1->clone();
std::string logger_name = "logger-name"; 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_1;
memory_buf_t formatted_2; memory_buf_t formatted_2;
@ -383,7 +383,7 @@ TEST_CASE("short filename formatter-1", "[pattern_formatter]")
memory_buf_t formatted; memory_buf_t formatted;
std::string logger_name = "logger-name"; std::string logger_name = "logger-name";
spdlog::source_loc source_loc{test_path, 123, "some_func()"}; 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); formatter.format(msg, formatted);
REQUIRE(fmt::to_string(formatted) == "myfile.cpp"); REQUIRE(fmt::to_string(formatted) == "myfile.cpp");
} }
@ -394,7 +394,7 @@ TEST_CASE("short filename formatter-2", "[pattern_formatter]")
memory_buf_t formatted; memory_buf_t formatted;
std::string logger_name = "logger-name"; std::string logger_name = "logger-name";
spdlog::source_loc source_loc{"myfile.cpp", 123, "some_func()"}; 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); formatter.format(msg, formatted);
REQUIRE(fmt::to_string(formatted) == "myfile.cpp:123"); REQUIRE(fmt::to_string(formatted) == "myfile.cpp:123");
} }
@ -405,7 +405,7 @@ TEST_CASE("short filename formatter-3", "[pattern_formatter]")
memory_buf_t formatted; memory_buf_t formatted;
std::string logger_name = "logger-name"; std::string logger_name = "logger-name";
spdlog::source_loc source_loc{"", 123, "some_func()"}; 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); formatter.format(msg, formatted);
REQUIRE(fmt::to_string(formatted) == " Hello"); REQUIRE(fmt::to_string(formatted) == " Hello");
} }
@ -416,7 +416,7 @@ TEST_CASE("full filename formatter", "[pattern_formatter]")
memory_buf_t formatted; memory_buf_t formatted;
std::string logger_name = "logger-name"; std::string logger_name = "logger-name";
spdlog::source_loc source_loc{test_path, 123, "some_func()"}; 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); formatter.format(msg, formatted);
REQUIRE(fmt::to_string(formatted) == test_path); REQUIRE(fmt::to_string(formatted) == test_path);
} }
@ -428,7 +428,7 @@ TEST_CASE("custom flags", "[pattern_formatter]")
memory_buf_t formatted; 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); formatter->format(msg, formatted);
auto expected = fmt::format("[logger-name] [custom1] [custom2] some message{}", spdlog::details::os::default_eol); auto expected = fmt::format("[logger-name] [custom1] [custom2] some message{}", spdlog::details::os::default_eol);
REQUIRE(fmt::to_string(formatted) == expected); REQUIRE(fmt::to_string(formatted) == expected);
@ -441,7 +441,7 @@ TEST_CASE("custom flags-padding", "[pattern_formatter]")
memory_buf_t formatted; 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); formatter->format(msg, formatted);
auto expected = fmt::format("[logger-name] [custom1] [ custom2] some message{}", spdlog::details::os::default_eol); auto expected = fmt::format("[logger-name] [custom1] [ custom2] some message{}", spdlog::details::os::default_eol);
REQUIRE(fmt::to_string(formatted) == expected); REQUIRE(fmt::to_string(formatted) == expected);
@ -453,6 +453,18 @@ TEST_CASE("custom flags-exception", "[pattern_formatter]")
formatter->add_flag<custom_test_flag>('t', "throw_me").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%u] %v"); formatter->add_flag<custom_test_flag>('t', "throw_me").add_flag<custom_test_flag>('u', "custom2").set_pattern("[%n] [%t] [%u] %v");
memory_buf_t formatted; 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); 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");
}

@ -15,7 +15,7 @@ TEST_CASE("time_point1", "[time_point log_msg]")
test_sink->set_delay(std::chrono::milliseconds(10)); test_sink->set_delay(std::chrono::milliseconds(10));
for (int i = 0; i < 5; i++) 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); test_sink->log(msg);
} }

Loading…
Cancel
Save