From 3e2d593dde16cf14c2a6c7e9cfea67826aad916a Mon Sep 17 00:00:00 2001 From: gabime Date: Thu, 18 Oct 2018 11:18:02 +0300 Subject: [PATCH 01/65] always initialize level and thread_id in log_msg --- include/spdlog/details/log_msg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 49987515..40c88eb6 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -35,9 +35,9 @@ struct log_msg log_msg &operator=(log_msg &&other) = delete; const std::string *logger_name{nullptr}; - level::level_enum level; + level::level_enum level {level::off}; log_clock::time_point time; - size_t thread_id; + size_t thread_id {0}; fmt::memory_buffer raw; size_t msg_id; From cb71fea0f6c9bb5722ca59e9b7917328217cfe5d Mon Sep 17 00:00:00 2001 From: Jerome Meyer Date: Wed, 17 Oct 2018 10:40:41 -0400 Subject: [PATCH 02/65] Use fmt::string_view when logging a C string to avoid unnecessary copy --- bench/bench.cpp | 39 ++++++++++++++++++++++ include/spdlog/details/fmt_helper.h | 12 +++++++ include/spdlog/details/log_msg.h | 3 ++ include/spdlog/details/logger_impl.h | 10 ++++-- include/spdlog/details/pattern_formatter.h | 4 +-- include/spdlog/details/thread_pool.h | 3 +- include/spdlog/logger.h | 3 +- include/spdlog/sinks/android_sink.h | 2 +- include/spdlog/sinks/syslog_sink.h | 7 +++- tests/test_misc.cpp | 19 +++++++++++ 10 files changed, 93 insertions(+), 9 deletions(-) diff --git a/bench/bench.cpp b/bench/bench.cpp index 0386be80..7ba0acf9 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -29,6 +29,7 @@ using namespace utils; void bench(int howmany, std::shared_ptr log); void bench_mt(int howmany, std::shared_ptr log, int thread_count); void bench_default_api(int howmany, std::shared_ptr log); +void bench_c_string(int howmany, std::shared_ptr log); int main(int argc, char *argv[]) { @@ -81,6 +82,21 @@ int main(int argc, char *argv[]) bench_default_api(howmany, spdlog::create("null_st")); + spdlog::info("**************************************************************"); + spdlog::info("C-string. Single thread, {:n} iterations", howmany); + spdlog::info("**************************************************************"); + + basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_cs.log", true); + bench_c_string(howmany, std::move(basic_st)); + + rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_cs.log", file_size, rotating_files); + bench_c_string(howmany, std::move(rotating_st)); + + daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_cs.log"); + bench_c_string(howmany, std::move(daily_st)); + + bench_c_string(howmany, spdlog::create("null_st")); + spdlog::info("**************************************************************"); spdlog::info("{:n} threads sharing same logger, {:n} iterations", threads, howmany); spdlog::info("**************************************************************"); @@ -173,3 +189,26 @@ void bench_default_api(int howmany, std::shared_ptr log) spdlog::set_default_logger(std::move(orig_default)); spdlog::info("{:<16} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d)); } + +void bench_c_string(int howmany, std::shared_ptr log) +{ + const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " \ + "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem " \ + "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec fringilla dui sed " \ + "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare " \ + "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; + using std::chrono::high_resolution_clock; + auto orig_default = spdlog::default_logger(); + spdlog::set_default_logger(log); + auto start = high_resolution_clock::now(); + for (auto i = 0; i < howmany; ++i) + { + spdlog::log(level::info, msg); + } + + auto delta = high_resolution_clock::now() - start; + auto delta_d = duration_cast>(delta).count(); + spdlog::drop(log->name()); + spdlog::set_default_logger(std::move(orig_default)); + spdlog::info("{:<16} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d)); +} diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 1518b2c0..8ce61df8 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -5,6 +5,7 @@ #pragma once #include "chrono" +#include "spdlog/details/log_msg.h" #include "spdlog/fmt/fmt.h" // Some fmt helpers to efficiently format and pad ints and strings @@ -40,6 +41,17 @@ inline void append_int(T n, fmt::basic_memory_buffer &dest) dest.append(i.data(), i.data() + i.size()); } +template +inline void append_msg(const details::log_msg &msg, fmt::basic_memory_buffer &dest) +{ + auto *c_buf = msg.c_string.data(); + if (c_buf != nullptr) { + dest.append(c_buf, c_buf + msg.c_string.size()); + } else { + append_buf(msg.raw, dest); + } +} + template inline void pad2(int n, fmt::basic_memory_buffer &dest) { diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 49987515..5e4bc37c 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -39,6 +39,9 @@ struct log_msg log_clock::time_point time; size_t thread_id; fmt::memory_buffer raw; + // if c_string.data() is not nullptr, c_string should be used as the message + // instead of raw above + fmt::string_view c_string; size_t msg_id; // info about wrapping the formatted text with color (updated by pattern_formatter). diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 46301ea1..d3cc62db 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -20,7 +20,7 @@ inline spdlog::logger::logger(std::string logger_name, It begin, It end) , flush_level_(level::off) , last_err_time_(0) , msg_counter_(1) // message counter will start from 1. 0-message id will be - // reserved for controll messages + // reserved for control messages { err_handler_ = [this](const std::string &msg) { this->default_err_handler_(msg); }; } @@ -70,8 +70,12 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar SPDLOG_CATCH_AND_HANDLE } -template inline void spdlog::logger::log(level::level_enum lvl, const char *msg) +{ + logn(lvl, msg, std::char_traits::length(msg)); +} + +inline void spdlog::logger::logn(level::level_enum lvl, const char *msg, size_t msg_len) { if (!should_log(lvl)) { @@ -80,7 +84,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *msg) try { details::log_msg log_msg(&name_, lvl); - details::fmt_helper::append_c_str(msg, log_msg.raw); + log_msg.c_string = fmt::string_view(msg, msg_len); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index f5a8406e..a8afa2b3 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -401,7 +401,7 @@ class v_formatter final : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_buf(msg.raw, dest); + fmt_helper::append_msg(msg, dest); } }; @@ -524,7 +524,7 @@ class full_formatter final : public flag_formatter msg.color_range_end = dest.size(); dest.push_back(']'); dest.push_back(' '); - fmt_helper::append_buf(msg.raw, dest); + fmt_helper::append_msg(msg, dest); } private: diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index 0c716c3b..b886e42f 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -1,5 +1,6 @@ #pragma once +#include "spdlog/details/fmt_helper.h" #include "spdlog/details/log_msg.h" #include "spdlog/details/mpmc_blocking_q.h" #include "spdlog/details/os.h" @@ -77,7 +78,7 @@ struct async_msg , msg_id(m.msg_id) , worker_ptr(std::move(worker)) { - fmt_helper::append_buf(m.raw, raw); + fmt_helper::append_msg(m, raw); } async_msg(async_logger_ptr &&worker, async_msg_type the_type) diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 1bcf4bc2..289296fd 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -46,9 +46,10 @@ public: template void log(level::level_enum lvl, const char *fmt, const Args &... args); - template void log(level::level_enum lvl, const char *msg); + void logn(level::level_enum lvl, const char *msg, size_t msg_len); + template void trace(const char *fmt, const Args &... args); diff --git a/include/spdlog/sinks/android_sink.h b/include/spdlog/sinks/android_sink.h index 8c3383c1..86837db9 100644 --- a/include/spdlog/sinks/android_sink.h +++ b/include/spdlog/sinks/android_sink.h @@ -47,7 +47,7 @@ protected: fmt::memory_buffer formatted; if (use_raw_msg_) { - details::fmt_helper::append_buf(msg.raw, formatted); + details::fmt_helper::append_msg(msg, formatted); } else { diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index cb76613d..36537e77 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -53,7 +53,12 @@ public: protected: void sink_it_(const details::log_msg &msg) override { - ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.raw).c_str()); + if (msg.c_string.data() != nullptr) + { + ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast(msg.c_string.size()), msg.c_string.data()); + } else { + ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.raw).c_str()); + } } void flush_() override {} diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index f69a3487..5b3b427b 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -231,3 +231,22 @@ TEST_CASE("default logger API", "[default logger]") spdlog::drop_all(); spdlog::set_pattern("%v"); } + +TEST_CASE("C string", "[c_string]") +{ + std::ostringstream oss; + auto oss_sink = std::make_shared(oss); + + spdlog::logger oss_logger("oss", oss_sink); + oss_logger.set_level(spdlog::level::debug); + oss_logger.set_pattern("*** %v"); + + const char *test_string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit massa nunc"; + + oss_logger.log(spdlog::level::debug, test_string); + REQUIRE(oss.str() == "*** " + std::string(test_string) + std::string(spdlog::details::os::default_eol)); + + oss.str(""); + oss_logger.logn(spdlog::level::debug, test_string, 11); + REQUIRE(oss.str() == "*** " + std::string(test_string, 11) + std::string(spdlog::details::os::default_eol)); +} From 6355e9895d14abc6d89873af526f25ad82b80839 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 02:15:50 +0300 Subject: [PATCH 03/65] Major change to log_msg - contain only string_view instead of buffer --- include/spdlog/details/fmt_helper.h | 32 ++++------------ include/spdlog/details/log_msg.h | 24 +++++++----- include/spdlog/details/logger_impl.h | 19 ++++------ include/spdlog/details/pattern_formatter.h | 44 +++++++++++++--------- include/spdlog/details/thread_pool.h | 12 +++--- include/spdlog/sinks/android_sink.h | 2 +- include/spdlog/sinks/syslog_sink.h | 7 +--- tests/test_misc.cpp | 19 ---------- tests/test_pattern_formatter.cpp | 12 ++++-- 9 files changed, 71 insertions(+), 100 deletions(-) diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 8ce61df8..0e606518 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -13,20 +13,6 @@ namespace spdlog { namespace details { namespace fmt_helper { -template -inline void append_str(const std::string &str, fmt::basic_memory_buffer &dest) -{ - auto *str_ptr = str.data(); - dest.append(str_ptr, str_ptr + str.size()); -} - -template -inline void append_c_str(const char *c_str, fmt::basic_memory_buffer &dest) -{ - auto len = std::char_traits::length(c_str); - dest.append(c_str, c_str + len); -} - template inline void append_buf(const fmt::basic_memory_buffer &buf, fmt::basic_memory_buffer &dest) { @@ -34,6 +20,13 @@ inline void append_buf(const fmt::basic_memory_buffer &buf, dest.append(buf_ptr, buf_ptr + buf.size()); } +template +inline void append_string_view(fmt::string_view view, fmt::basic_memory_buffer &dest) +{ + auto *buf_ptr = view.data(); + dest.append(buf_ptr, buf_ptr + view.size()); +} + template inline void append_int(T n, fmt::basic_memory_buffer &dest) { @@ -41,17 +34,6 @@ inline void append_int(T n, fmt::basic_memory_buffer &dest) dest.append(i.data(), i.data() + i.size()); } -template -inline void append_msg(const details::log_msg &msg, fmt::basic_memory_buffer &dest) -{ - auto *c_buf = msg.c_string.data(); - if (c_buf != nullptr) { - dest.append(c_buf, c_buf + msg.c_string.size()); - } else { - append_buf(msg.raw, dest); - } -} - template inline void pad2(int n, fmt::basic_memory_buffer &dest) { diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index bde4b978..71ed7208 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -17,7 +17,7 @@ struct log_msg { log_msg() = default; - log_msg(const std::string *loggers_name, level::level_enum lvl) + log_msg(const std::string *loggers_name, level::level_enum lvl, fmt::string_view view) : logger_name(loggers_name) , level(lvl) #ifndef SPDLOG_NO_DATETIME @@ -26,27 +26,31 @@ struct log_msg #ifndef SPDLOG_NO_THREAD_ID , thread_id(os::thread_id()) + , payload(view) #endif { } - log_msg(const log_msg &other) = delete; - log_msg(log_msg &&other) = delete; - log_msg &operator=(log_msg &&other) = delete; + log_msg(const log_msg &other) = default; + log_msg(log_msg &&other) = default; + log_msg &operator=(log_msg &&other) = default; const std::string *logger_name{nullptr}; - level::level_enum level {level::off}; + level::level_enum level{level::off}; log_clock::time_point time; - size_t thread_id {0}; - fmt::memory_buffer raw; - // if c_string.data() is not nullptr, c_string should be used as the message - // instead of raw above - fmt::string_view c_string; + size_t thread_id{0}; size_t msg_id; // info about wrapping the formatted text with color (updated by pattern_formatter). mutable size_t color_range_start{0}; mutable size_t color_range_end{0}; + + operator fmt::string_view() const SPDLOG_NOEXCEPT + { + return payload; + } + + const fmt::string_view payload; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index d3cc62db..a557d45d 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -63,28 +63,24 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar try { - details::log_msg log_msg(&name_, lvl); - fmt::format_to(log_msg.raw, fmt, args...); + fmt::memory_buffer buf; + fmt::format_to(buf, fmt, args...); + details::log_msg log_msg(&name_, lvl, fmt::string_view(buf.data(), buf.size())); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE } inline void spdlog::logger::log(level::level_enum lvl, const char *msg) -{ - logn(lvl, msg, std::char_traits::length(msg)); -} - -inline void spdlog::logger::logn(level::level_enum lvl, const char *msg, size_t msg_len) { if (!should_log(lvl)) { return; } + try { - details::log_msg log_msg(&name_, lvl); - log_msg.c_string = fmt::string_view(msg, msg_len); + details::log_msg log_msg(&name_, lvl, msg); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE @@ -99,8 +95,9 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) } try { - details::log_msg log_msg(&name_, lvl); - fmt::format_to(log_msg.raw, "{}", msg); + fmt::memory_buffer buf; + fmt::format_to(buf, "{}", msg); + details::log_msg log_msg(&name_, lvl, fmt::string_view(buf.data(), buf.size())); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index a8afa2b3..de384948 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -38,7 +38,8 @@ class name_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_str(*msg.logger_name, dest); + // fmt_helper::append_str(*msg.logger_name, dest); + fmt_helper::append_string_view(*msg.logger_name, dest); } }; @@ -47,7 +48,8 @@ class level_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(level::to_c_str(msg.level), dest); + // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); + fmt_helper::append_string_view(level::to_c_str(msg.level), dest); } }; @@ -56,7 +58,8 @@ class short_level_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(level::to_short_c_str(msg.level), dest); + // fmt_helper::append_string_view(level::to_short_c_str(msg.level), dest); + fmt_helper::append_string_view(level::to_short_c_str(msg.level), dest); } }; @@ -80,7 +83,8 @@ class a_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(days[tm_time.tm_wday], dest); + // fmt_helper::append_string_view(days[tm_time.tm_wday], dest); + fmt_helper::append_string_view(days[tm_time.tm_wday], dest); } }; @@ -90,7 +94,8 @@ class A_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(full_days[tm_time.tm_wday], dest); + // fmt_helper::append_string_view(full_days[tm_time.tm_wday], dest); + fmt_helper::append_string_view(full_days[tm_time.tm_wday], dest); } }; @@ -100,7 +105,8 @@ class b_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(months[tm_time.tm_mon], dest); + // fmt_helper::append_string_view(months[tm_time.tm_mon], dest); + fmt_helper::append_string_view(months[tm_time.tm_mon], dest); } }; @@ -111,7 +117,7 @@ class B_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(full_months[tm_time.tm_mon], dest); + fmt_helper::append_string_view(full_months[tm_time.tm_mon], dest); } }; @@ -123,9 +129,9 @@ class c_formatter final : public flag_formatter // fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], // months[tm_time.tm_mon], tm_time.tm_mday); // date - fmt_helper::append_c_str(days[tm_time.tm_wday], dest); + fmt_helper::append_string_view(days[tm_time.tm_wday], dest); dest.push_back(' '); - fmt_helper::append_c_str(months[tm_time.tm_mon], dest); + fmt_helper::append_string_view(months[tm_time.tm_mon], dest); dest.push_back(' '); fmt_helper::append_int(tm_time.tm_mday, dest); dest.push_back(' '); @@ -272,7 +278,7 @@ class p_formatter final : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_c_str(ampm(tm_time), dest); + fmt_helper::append_string_view(ampm(tm_time), dest); } }; @@ -287,7 +293,7 @@ class r_formatter final : public flag_formatter dest.push_back(':'); fmt_helper::pad2(tm_time.tm_sec, dest); dest.push_back(' '); - fmt_helper::append_c_str(ampm(tm_time), dest); + fmt_helper::append_string_view(ampm(tm_time), dest); } }; @@ -401,7 +407,7 @@ class v_formatter final : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_msg(msg, dest); + fmt_helper::append_string_view(msg, dest); } }; @@ -433,7 +439,7 @@ public: } void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_str(str_, dest); + fmt_helper::append_string_view(str_, dest); } private: @@ -511,7 +517,8 @@ class full_formatter final : public flag_formatter if (!msg.logger_name->empty()) { dest.push_back('['); - fmt_helper::append_str(*msg.logger_name, dest); + // fmt_helper::append_str(*msg.logger_name, dest); + fmt_helper::append_string_view(*msg.logger_name, dest); dest.push_back(']'); dest.push_back(' '); } @@ -520,11 +527,13 @@ class full_formatter final : public flag_formatter dest.push_back('['); // wrap the level name with color msg.color_range_start = dest.size(); - fmt_helper::append_c_str(level::to_c_str(msg.level), dest); + // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); + fmt_helper::append_string_view(level::to_c_str(msg.level), dest); msg.color_range_end = dest.size(); dest.push_back(']'); dest.push_back(' '); - fmt_helper::append_msg(msg, dest); + // fmt_helper::append_string_view(msg.msg(), dest); + fmt_helper::append_string_view(msg, dest); } private: @@ -571,7 +580,8 @@ public: f->format(msg, cached_tm_, dest); } // write eol - details::fmt_helper::append_c_str(eol_.c_str(), dest); + // details::fmt_helper::append_string_view(eol_.c_str(), dest); + details::fmt_helper::append_string_view(eol_.c_str(), dest); } private: diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index b886e42f..63f27e7b 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -78,7 +78,7 @@ struct async_msg , msg_id(m.msg_id) , worker_ptr(std::move(worker)) { - fmt_helper::append_msg(m, raw); + fmt_helper::append_string_view(m, raw); } async_msg(async_logger_ptr &&worker, async_msg_type the_type) @@ -92,16 +92,15 @@ struct async_msg } // copy into log_msg - void to_log_msg(log_msg &msg) + log_msg to_log_msg() { - msg.logger_name = &worker_ptr->name(); - msg.level = level; + log_msg msg(&worker_ptr->name(), level, fmt::string_view(raw.data(), raw.size())); msg.time = time; msg.thread_id = thread_id; - fmt_helper::append_buf(raw, msg.raw); msg.msg_id = msg_id; msg.color_range_start = 0; msg.color_range_end = 0; + return msg; } }; @@ -204,8 +203,7 @@ private: { case async_msg_type::log: { - log_msg msg; - incoming_async_msg.to_log_msg(msg); + auto msg = incoming_async_msg.to_log_msg(); incoming_async_msg.worker_ptr->backend_log_(msg); return true; } diff --git a/include/spdlog/sinks/android_sink.h b/include/spdlog/sinks/android_sink.h index 86837db9..1286c173 100644 --- a/include/spdlog/sinks/android_sink.h +++ b/include/spdlog/sinks/android_sink.h @@ -47,7 +47,7 @@ protected: fmt::memory_buffer formatted; if (use_raw_msg_) { - details::fmt_helper::append_msg(msg, formatted); + details::fmt_helper::append_string_view(msg, formatted); } else { diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index 36537e77..d1c78210 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -53,12 +53,7 @@ public: protected: void sink_it_(const details::log_msg &msg) override { - if (msg.c_string.data() != nullptr) - { - ::syslog(syslog_prio_from_level(msg), "%.*s", static_cast(msg.c_string.size()), msg.c_string.data()); - } else { - ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.raw).c_str()); - } + ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg).c_str()); } void flush_() override {} diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index 5b3b427b..f69a3487 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -231,22 +231,3 @@ TEST_CASE("default logger API", "[default logger]") spdlog::drop_all(); spdlog::set_pattern("%v"); } - -TEST_CASE("C string", "[c_string]") -{ - std::ostringstream oss; - auto oss_sink = std::make_shared(oss); - - spdlog::logger oss_logger("oss", oss_sink); - oss_logger.set_level(spdlog::level::debug); - oss_logger.set_pattern("*** %v"); - - const char *test_string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit massa nunc"; - - oss_logger.log(spdlog::level::debug, test_string); - REQUIRE(oss.str() == "*** " + std::string(test_string) + std::string(spdlog::details::os::default_eol)); - - oss.str(""); - oss_logger.logn(spdlog::level::debug, test_string, 11); - REQUIRE(oss.str() == "*** " + std::string(test_string, 11) + std::string(spdlog::details::os::default_eol)); -} diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index 17b61612..df48dc35 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -60,9 +60,12 @@ TEST_CASE("date MM/DD/YY ", "[pattern_formatter]") TEST_CASE("color range test1", "[pattern_formatter]") { auto formatter = std::make_shared("%^%v%$", spdlog::pattern_time_type::local, "\n"); - spdlog::details::log_msg msg; - fmt::format_to(msg.raw, "Hello"); + + fmt::memory_buffer buf; + fmt::format_to(buf, "Hello"); fmt::memory_buffer formatted; + std::string logger_name = "test"; + spdlog::details::log_msg msg(&logger_name, spdlog::level::info, fmt::string_view(buf.data(), buf.size())); formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_end == 5); @@ -93,8 +96,9 @@ TEST_CASE("color range test3", "[pattern_formatter]") TEST_CASE("color range test4", "[pattern_formatter]") { auto formatter = std::make_shared("XX%^YYY%$", spdlog::pattern_time_type::local, "\n"); - spdlog::details::log_msg msg; - fmt::format_to(msg.raw, "ignored"); + std::string logger_name = "test"; + spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored"); + fmt::memory_buffer formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 2); From a5a39c52b05647266facf41961e9270212b4ad44 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 02:45:35 +0300 Subject: [PATCH 04/65] Added nullptr check to append_string_view --- include/spdlog/details/fmt_helper.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 0e606518..4de48899 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -24,7 +24,10 @@ template inline void append_string_view(fmt::string_view view, fmt::basic_memory_buffer &dest) { auto *buf_ptr = view.data(); - dest.append(buf_ptr, buf_ptr + view.size()); + if(buf_ptr != nullptr) + { + dest.append(buf_ptr, buf_ptr + view.size()); + } } template From 23da9f13b069ac90de415e28601514468565bbe9 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 16:31:43 +0300 Subject: [PATCH 05/65] Fixed valgrind warning in example --- example/example.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/example/example.cpp b/example/example.cpp index 15ca856e..6ee37af3 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -146,7 +146,11 @@ void async_example() #include "spdlog/fmt/bin_to_hex.h" void binary_example() { - std::array buf; + std::vector buf; + for(int i = 0; i < 80; i++) + { + buf.push_back(static_cast(i & 0xff)); + } spdlog::info("Binary example: {}", spdlog::to_hex(buf)); spdlog::info("Another binary example:{:n}", spdlog::to_hex(std::begin(buf), std::begin(buf) + 10)); // more examples: From c2a9bf997481adc360bdf621ff8ab148a695cc5a Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 16:48:22 +0300 Subject: [PATCH 06/65] Small refactoring and support wchar again --- include/spdlog/details/fmt_helper.h | 5 +++++ include/spdlog/details/logger_impl.h | 13 +++++++++---- include/spdlog/details/pattern_formatter.h | 3 --- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 4de48899..818c988f 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -13,6 +13,11 @@ namespace spdlog { namespace details { namespace fmt_helper { +template +inline fmt::string_view to_string_view(const fmt::basic_memory_buffer &buf) SPDLOG_NOEXCEPT +{ + return fmt::string_view(buf.data(), buf.size()); +} template inline void append_buf(const fmt::basic_memory_buffer &buf, fmt::basic_memory_buffer &dest) { diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index a557d45d..7e307d7f 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -63,9 +63,10 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar try { + using details::fmt_helper::to_string_view; fmt::memory_buffer buf; fmt::format_to(buf, fmt, args...); - details::log_msg log_msg(&name_, lvl, fmt::string_view(buf.data(), buf.size())); + details::log_msg log_msg(&name_, lvl, to_string_view(buf)); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE @@ -95,9 +96,10 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) } try { + using details::fmt_helper::to_string_view; fmt::memory_buffer buf; fmt::format_to(buf, "{}", msg); - details::log_msg log_msg(&name_, lvl, fmt::string_view(buf.data(), buf.size())); + details::log_msg log_msg(&name_, lvl, to_string_view(buf)); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE @@ -209,11 +211,14 @@ inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const try { // format to wmemory_buffer and convert to utf8 - details::log_msg log_msg(&name_, lvl); + using details::fmt_helper::to_string_view; fmt::wmemory_buffer wbuf; fmt::format_to(wbuf, fmt, args...); - wbuf_to_utf8buf(wbuf, log_msg.raw); + fmt::memory_buffer buf; + wbuf_to_utf8buf(wbuf, buf); + details::log_msg log_msg(&name_, lvl, to_string_view(buf)); sink_it_(log_msg); + } SPDLOG_CATCH_AND_HANDLE } diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index de384948..d1ff0e9c 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -83,7 +83,6 @@ class a_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - // fmt_helper::append_string_view(days[tm_time.tm_wday], dest); fmt_helper::append_string_view(days[tm_time.tm_wday], dest); } }; @@ -94,7 +93,6 @@ class A_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - // fmt_helper::append_string_view(full_days[tm_time.tm_wday], dest); fmt_helper::append_string_view(full_days[tm_time.tm_wday], dest); } }; @@ -105,7 +103,6 @@ class b_formatter : public flag_formatter { void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - // fmt_helper::append_string_view(months[tm_time.tm_mon], dest); fmt_helper::append_string_view(months[tm_time.tm_mon], dest); } }; From 70bef682b0c6a4d2df2729dac82f2faa45823e5f Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 17:12:02 +0300 Subject: [PATCH 07/65] Fixed clang-tidy warning about implicit conversion to string_view --- include/spdlog/details/log_msg.h | 5 ----- include/spdlog/details/pattern_formatter.h | 4 ++-- include/spdlog/details/thread_pool.h | 2 +- include/spdlog/sinks/android_sink.h | 2 +- include/spdlog/sinks/syslog_sink.h | 2 +- 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 71ed7208..d7703625 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -45,11 +45,6 @@ struct log_msg mutable size_t color_range_start{0}; mutable size_t color_range_end{0}; - operator fmt::string_view() const SPDLOG_NOEXCEPT - { - return payload; - } - const fmt::string_view payload; }; } // namespace details diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index d1ff0e9c..86833c7e 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -404,7 +404,7 @@ class v_formatter final : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(msg, dest); + fmt_helper::append_string_view(msg.payload, dest); } }; @@ -530,7 +530,7 @@ class full_formatter final : public flag_formatter dest.push_back(']'); dest.push_back(' '); // fmt_helper::append_string_view(msg.msg(), dest); - fmt_helper::append_string_view(msg, dest); + fmt_helper::append_string_view(msg.payload, dest); } private: diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index 63f27e7b..2743fd1e 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -78,7 +78,7 @@ struct async_msg , msg_id(m.msg_id) , worker_ptr(std::move(worker)) { - fmt_helper::append_string_view(m, raw); + fmt_helper::append_string_view(m.payload, raw); } async_msg(async_logger_ptr &&worker, async_msg_type the_type) diff --git a/include/spdlog/sinks/android_sink.h b/include/spdlog/sinks/android_sink.h index 1286c173..0742b247 100644 --- a/include/spdlog/sinks/android_sink.h +++ b/include/spdlog/sinks/android_sink.h @@ -47,7 +47,7 @@ protected: fmt::memory_buffer formatted; if (use_raw_msg_) { - details::fmt_helper::append_string_view(msg, formatted); + details::fmt_helper::append_string_view(msg.payload, formatted); } else { diff --git a/include/spdlog/sinks/syslog_sink.h b/include/spdlog/sinks/syslog_sink.h index d1c78210..4df49b87 100644 --- a/include/spdlog/sinks/syslog_sink.h +++ b/include/spdlog/sinks/syslog_sink.h @@ -53,7 +53,7 @@ public: protected: void sink_it_(const details::log_msg &msg) override { - ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg).c_str()); + ::syslog(syslog_prio_from_level(msg), "%s", fmt::to_string(msg.payload).c_str()); } void flush_() override {} From 4e3e80109a005f3d24e164f766de6076cc07a689 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 17:12:35 +0300 Subject: [PATCH 08/65] Code formatting --- bench/bench.cpp | 10 +++++----- example/example.cpp | 2 +- include/spdlog/details/fmt_helper.h | 2 +- include/spdlog/details/logger_impl.h | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/bench/bench.cpp b/bench/bench.cpp index 7ba0acf9..9c06cc0e 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -192,11 +192,11 @@ void bench_default_api(int howmany, std::shared_ptr log) void bench_c_string(int howmany, std::shared_ptr log) { - const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " \ - "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem " \ - "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec fringilla dui sed " \ - "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare " \ - "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; + const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " + "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem " + "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec fringilla dui sed " + "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare " + "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; using std::chrono::high_resolution_clock; auto orig_default = spdlog::default_logger(); spdlog::set_default_logger(log); diff --git a/example/example.cpp b/example/example.cpp index 6ee37af3..1eea343e 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -147,7 +147,7 @@ void async_example() void binary_example() { std::vector buf; - for(int i = 0; i < 80; i++) + for (int i = 0; i < 80; i++) { buf.push_back(static_cast(i & 0xff)); } diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 818c988f..5ad979df 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -29,7 +29,7 @@ template inline void append_string_view(fmt::string_view view, fmt::basic_memory_buffer &dest) { auto *buf_ptr = view.data(); - if(buf_ptr != nullptr) + if (buf_ptr != nullptr) { dest.append(buf_ptr, buf_ptr + view.size()); } diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 7e307d7f..e9b7a8e8 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -218,7 +218,6 @@ inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const wbuf_to_utf8buf(wbuf, buf); details::log_msg log_msg(&name_, lvl, to_string_view(buf)); sink_it_(log_msg); - } SPDLOG_CATCH_AND_HANDLE } From dd9d7e62d56229802e772b96ba6bd4ffe03d031d Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 19 Oct 2018 17:16:51 +0300 Subject: [PATCH 09/65] bench C-string title --- bench/bench.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/bench.cpp b/bench/bench.cpp index 9c06cc0e..756b04a2 100644 --- a/bench/bench.cpp +++ b/bench/bench.cpp @@ -83,7 +83,7 @@ int main(int argc, char *argv[]) bench_default_api(howmany, spdlog::create("null_st")); spdlog::info("**************************************************************"); - spdlog::info("C-string. Single thread, {:n} iterations", howmany); + spdlog::info("C-string (500 bytes). Single thread, {:n} iterations", howmany); spdlog::info("**************************************************************"); basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_cs.log", true); From 2ad191aebab3fd21a4281f0cad78678983010bc3 Mon Sep 17 00:00:00 2001 From: Gabi Melman Date: Sat, 20 Oct 2018 18:27:58 +0300 Subject: [PATCH 10/65] Update log_msg.h --- include/spdlog/details/log_msg.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index d7703625..8cd51f08 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -32,8 +32,7 @@ struct log_msg } log_msg(const log_msg &other) = default; - log_msg(log_msg &&other) = default; - log_msg &operator=(log_msg &&other) = default; + log_msg &operator=(const log_msg &other) = default; const std::string *logger_name{nullptr}; level::level_enum level{level::off}; From 894438d5fbeaf471b71554e41fd4137ecd162651 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 12:46:58 +0300 Subject: [PATCH 11/65] Better support for string_view --- include/spdlog/common.h | 7 +++++++ include/spdlog/details/fmt_helper.h | 6 +++--- include/spdlog/details/log_msg.h | 4 ++-- include/spdlog/details/pattern_formatter.h | 3 ++- include/spdlog/details/thread_pool.h | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/spdlog/common.h b/include/spdlog/common.h index b6147346..0346471a 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -56,6 +56,13 @@ using sink_ptr = std::shared_ptr; using sinks_init_list = std::initializer_list; using log_err_handler = std::function; +// string_view type - either std::string_view or fmt::string_view (pre c++17) +#if defined(FMT_USE_STD_STRING_VIEW) +using string_view_type = std::string_view; +#else +using string_view_type = fmt::string_view; +#endif + #if defined(SPDLOG_NO_ATOMIC_LEVELS) using level_t = details::null_atomic_int; #else diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 5ad979df..45dceb29 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -14,9 +14,9 @@ namespace details { namespace fmt_helper { template -inline fmt::string_view to_string_view(const fmt::basic_memory_buffer &buf) SPDLOG_NOEXCEPT +inline spdlog::string_view_type to_string_view(const fmt::basic_memory_buffer &buf) SPDLOG_NOEXCEPT { - return fmt::string_view(buf.data(), buf.size()); + return spdlog::string_view_type(buf.data(), buf.size()); } template inline void append_buf(const fmt::basic_memory_buffer &buf, fmt::basic_memory_buffer &dest) @@ -26,7 +26,7 @@ inline void append_buf(const fmt::basic_memory_buffer &buf, } template -inline void append_string_view(fmt::string_view view, fmt::basic_memory_buffer &dest) +inline void append_string_view(spdlog::string_view_type view, fmt::basic_memory_buffer &dest) { auto *buf_ptr = view.data(); if (buf_ptr != nullptr) diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 8cd51f08..122eabf0 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -17,7 +17,7 @@ struct log_msg { log_msg() = default; - log_msg(const std::string *loggers_name, level::level_enum lvl, fmt::string_view view) + log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_type view) : logger_name(loggers_name) , level(lvl) #ifndef SPDLOG_NO_DATETIME @@ -44,7 +44,7 @@ struct log_msg mutable size_t color_range_start{0}; mutable size_t color_range_end{0}; - const fmt::string_view payload; + const string_view_type payload; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 86833c7e..f80a18c5 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -39,7 +39,7 @@ class name_formatter : public flag_formatter void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { // fmt_helper::append_str(*msg.logger_name, dest); - fmt_helper::append_string_view(*msg.logger_name, dest); + fmt_helper::append_string_view(string_view_type(*msg.logger_name), dest); } }; @@ -49,6 +49,7 @@ class level_formatter : public flag_formatter void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); + spdlog::string_view_type t("SSSSSSS"); fmt_helper::append_string_view(level::to_c_str(msg.level), dest); } }; diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index 2743fd1e..4b774652 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -94,7 +94,7 @@ struct async_msg // copy into log_msg log_msg to_log_msg() { - log_msg msg(&worker_ptr->name(), level, fmt::string_view(raw.data(), raw.size())); + log_msg msg(&worker_ptr->name(), level, string_view_type(raw.data(), raw.size())); msg.time = time; msg.thread_id = thread_id; msg.msg_id = msg_id; From 57637334908b583778acbc029db0ce5bf49305a3 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 12:49:04 +0300 Subject: [PATCH 12/65] Fix sdk version in msvc example --- example/example.vcxproj | 1 - 1 file changed, 1 deletion(-) diff --git a/example/example.vcxproj b/example/example.vcxproj index 0cedd620..c752a8e9 100644 --- a/example/example.vcxproj +++ b/example/example.vcxproj @@ -25,7 +25,6 @@ {9E5AB93A-0CCE-4BAC-9FCB-0FC9CB5EB8D2} Win32Proj . - 10.0.16299.0 From 0584d6d89b181b5954da6171ceed51bb92190e1b Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 18:38:37 +0300 Subject: [PATCH 13/65] Removed logn declaration --- include/spdlog/logger.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 289296fd..90610a43 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -47,9 +47,7 @@ public: void log(level::level_enum lvl, const char *fmt, const Args &... args); void log(level::level_enum lvl, const char *msg); - - void logn(level::level_enum lvl, const char *msg, size_t msg_len); - + template void trace(const char *fmt, const Args &... args); From 8d2c956563baa9ac4e2b2a5f8ea831dab56b44f8 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 19:04:55 +0300 Subject: [PATCH 14/65] Optimize log(const T&) if can be statically converted to string_view --- include/spdlog/details/logger_impl.h | 25 ++++++++++++++++++++++--- include/spdlog/logger.h | 8 +++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index e9b7a8e8..8af8177f 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -71,7 +71,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar } SPDLOG_CATCH_AND_HANDLE } - +template<> inline void spdlog::logger::log(level::level_enum lvl, const char *msg) { if (!should_log(lvl)) @@ -81,13 +81,29 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *msg) try { - details::log_msg log_msg(&name_, lvl, msg); + details::log_msg log_msg(&name_, lvl, spdlog::string_view_type(msg)); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE } -template + +template::value, T>::type *> +inline void spdlog::logger::log(level::level_enum lvl, const T &msg) +{ + if (!should_log(lvl)) + { + return; + } + try + { + details::log_msg log_msg(&name_, lvl, spdlog::string_view_type(msg)); + sink_it_(log_msg); + } + SPDLOG_CATCH_AND_HANDLE +} + +template::value, T>::type*> inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { if (!should_log(lvl)) @@ -105,6 +121,9 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) SPDLOG_CATCH_AND_HANDLE } + + + template inline void spdlog::logger::trace(const char *fmt, const Args &... args) { diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 90610a43..fd428724 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -46,6 +46,7 @@ public: template void log(level::level_enum lvl, const char *fmt, const Args &... args); + template<> void log(level::level_enum lvl, const char *msg); template @@ -93,7 +94,12 @@ public: #endif // _WIN32 #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT - template + // T can be statically converted to string_view + template::value, T>::type * = nullptr> + void log(level::level_enum lvl, const T &); + + // T cannot be statically converted to string_view + template::value, T>::type * = nullptr> void log(level::level_enum lvl, const T &); template From 9daad800a8cc86940d3eb8912cfca6cbc177e43f Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 19:26:11 +0300 Subject: [PATCH 15/65] Fix mingw compilation --- include/spdlog/details/logger_impl.h | 2 +- include/spdlog/logger.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 8af8177f..86eb45cb 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -71,7 +71,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Ar } SPDLOG_CATCH_AND_HANDLE } -template<> + inline void spdlog::logger::log(level::level_enum lvl, const char *msg) { if (!should_log(lvl)) diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index fd428724..0cac21d4 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -45,8 +45,7 @@ public: template void log(level::level_enum lvl, const char *fmt, const Args &... args); - - template<> + void log(level::level_enum lvl, const char *msg); template From 1bdd556d3b1d7e83f972415aae5995325f3ea7b8 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 23:23:40 +0300 Subject: [PATCH 16/65] code formatting --- include/spdlog/details/logger_impl.h | 6 +----- include/spdlog/logger.h | 10 +++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 86eb45cb..de529dce 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -87,7 +87,6 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *msg) SPDLOG_CATCH_AND_HANDLE } - template::value, T>::type *> inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { @@ -103,7 +102,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) SPDLOG_CATCH_AND_HANDLE } -template::value, T>::type*> +template::value, T>::type *> inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { if (!should_log(lvl)) @@ -121,9 +120,6 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) SPDLOG_CATCH_AND_HANDLE } - - - template inline void spdlog::logger::trace(const char *fmt, const Args &... args) { diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 0cac21d4..56dcb8f5 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -45,9 +45,9 @@ public: template void log(level::level_enum lvl, const char *fmt, const Args &... args); - + void log(level::level_enum lvl, const char *msg); - + template void trace(const char *fmt, const Args &... args); @@ -93,12 +93,12 @@ public: #endif // _WIN32 #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT - // T can be statically converted to string_view + // T can be statically converted to string_view template::value, T>::type * = nullptr> void log(level::level_enum lvl, const T &); - // T cannot be statically converted to string_view - template::value, T>::type * = nullptr> + // T cannot be statically converted to string_view + template::value, T>::type * = nullptr> void log(level::level_enum lvl, const T &); template From 871cca240119f038cc90a41574f5dcaad94f75b8 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 23:48:11 +0300 Subject: [PATCH 17/65] Fixed pattern formatter --- include/spdlog/details/pattern_formatter.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index f80a18c5..435eb1b2 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -32,13 +32,12 @@ public: }; /////////////////////////////////////////////////////////////////////// -// name & level pattern appenders +// name & level pattern appender /////////////////////////////////////////////////////////////////////// class name_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - // fmt_helper::append_str(*msg.logger_name, dest); fmt_helper::append_string_view(string_view_type(*msg.logger_name), dest); } }; @@ -48,8 +47,6 @@ class level_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); - spdlog::string_view_type t("SSSSSSS"); fmt_helper::append_string_view(level::to_c_str(msg.level), dest); } }; @@ -59,7 +56,6 @@ class short_level_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - // fmt_helper::append_string_view(level::to_short_c_str(msg.level), dest); fmt_helper::append_string_view(level::to_short_c_str(msg.level), dest); } }; From 392d126372844fe581c84a8702b86b596e1b2fbc Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 21 Oct 2018 23:50:07 +0300 Subject: [PATCH 18/65] Renamed string_view_type -> string_view_t --- include/spdlog/common.h | 4 ++-- include/spdlog/details/fmt_helper.h | 6 +++--- include/spdlog/details/log_msg.h | 4 ++-- include/spdlog/details/logger_impl.h | 8 ++++---- include/spdlog/details/pattern_formatter.h | 2 +- include/spdlog/details/thread_pool.h | 2 +- include/spdlog/logger.h | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/spdlog/common.h b/include/spdlog/common.h index 0346471a..51c5195c 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -58,9 +58,9 @@ using log_err_handler = std::function; // string_view type - either std::string_view or fmt::string_view (pre c++17) #if defined(FMT_USE_STD_STRING_VIEW) -using string_view_type = std::string_view; +using string_view_t = std::string_view; #else -using string_view_type = fmt::string_view; +using string_view_t = fmt::string_view; #endif #if defined(SPDLOG_NO_ATOMIC_LEVELS) diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 45dceb29..21bbd154 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -14,9 +14,9 @@ namespace details { namespace fmt_helper { template -inline spdlog::string_view_type to_string_view(const fmt::basic_memory_buffer &buf) SPDLOG_NOEXCEPT +inline spdlog::string_view_t to_string_view(const fmt::basic_memory_buffer &buf) SPDLOG_NOEXCEPT { - return spdlog::string_view_type(buf.data(), buf.size()); + return spdlog::string_view_t(buf.data(), buf.size()); } template inline void append_buf(const fmt::basic_memory_buffer &buf, fmt::basic_memory_buffer &dest) @@ -26,7 +26,7 @@ inline void append_buf(const fmt::basic_memory_buffer &buf, } template -inline void append_string_view(spdlog::string_view_type view, fmt::basic_memory_buffer &dest) +inline void append_string_view(spdlog::string_view_t view, fmt::basic_memory_buffer &dest) { auto *buf_ptr = view.data(); if (buf_ptr != nullptr) diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 122eabf0..21f8bc6d 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -17,7 +17,7 @@ struct log_msg { log_msg() = default; - log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_type view) + log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_t view) : logger_name(loggers_name) , level(lvl) #ifndef SPDLOG_NO_DATETIME @@ -44,7 +44,7 @@ struct log_msg mutable size_t color_range_start{0}; mutable size_t color_range_end{0}; - const string_view_type payload; + const string_view_t payload; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index de529dce..54ae4be1 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -81,13 +81,13 @@ inline void spdlog::logger::log(level::level_enum lvl, const char *msg) try { - details::log_msg log_msg(&name_, lvl, spdlog::string_view_type(msg)); + details::log_msg log_msg(&name_, lvl, spdlog::string_view_t(msg)); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE } -template::value, T>::type *> +template::value, T>::type *> inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { if (!should_log(lvl)) @@ -96,13 +96,13 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) } try { - details::log_msg log_msg(&name_, lvl, spdlog::string_view_type(msg)); + details::log_msg log_msg(&name_, lvl, spdlog::string_view_t(msg)); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE } -template::value, T>::type *> +template::value, T>::type *> inline void spdlog::logger::log(level::level_enum lvl, const T &msg) { if (!should_log(lvl)) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 435eb1b2..89811d1f 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -38,7 +38,7 @@ class name_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(string_view_type(*msg.logger_name), dest); + fmt_helper::append_string_view(string_view_t(*msg.logger_name), dest); } }; diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index 4b774652..de01ad58 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -94,7 +94,7 @@ struct async_msg // copy into log_msg log_msg to_log_msg() { - log_msg msg(&worker_ptr->name(), level, string_view_type(raw.data(), raw.size())); + log_msg msg(&worker_ptr->name(), level, string_view_t(raw.data(), raw.size())); msg.time = time; msg.thread_id = thread_id; msg.msg_id = msg_id; diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 56dcb8f5..1e5db22b 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -94,11 +94,11 @@ public: #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT // T can be statically converted to string_view - template::value, T>::type * = nullptr> + template::value, T>::type * = nullptr> void log(level::level_enum lvl, const T &); // T cannot be statically converted to string_view - template::value, T>::type * = nullptr> + template::value, T>::type * = nullptr> void log(level::level_enum lvl, const T &); template From cadb3d7da22b0d413004804be4cf839593399ac4 Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 22 Oct 2018 00:14:07 +0300 Subject: [PATCH 19/65] Fixed test --- tests/test_pattern_formatter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index df48dc35..8b8c9447 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -65,7 +65,7 @@ TEST_CASE("color range test1", "[pattern_formatter]") fmt::format_to(buf, "Hello"); fmt::memory_buffer formatted; std::string logger_name = "test"; - spdlog::details::log_msg msg(&logger_name, spdlog::level::info, fmt::string_view(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); From 99e23b41ebf058d21b854a75638bbed45789b380 Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 22 Oct 2018 00:47:51 +0300 Subject: [PATCH 20/65] use static_cast instead of ctor in logger impl --- include/spdlog/details/logger_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 54ae4be1..a29f7ad7 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -96,7 +96,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) } try { - details::log_msg log_msg(&name_, lvl, spdlog::string_view_t(msg)); + details::log_msg log_msg(&name_, lvl, static_cast(msg)); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE From 240a58fd6e8bfe8fa62dd3ea777d1909f6d89a72 Mon Sep 17 00:00:00 2001 From: gabime Date: Wed, 24 Oct 2018 08:47:02 +0300 Subject: [PATCH 21/65] Fixed issue #881 --- include/spdlog/details/logger_impl.h | 2 +- include/spdlog/logger.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index a29f7ad7..e7385b5d 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -293,7 +293,7 @@ inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handle err_handler_ = std::move(err_handler); } -inline spdlog::log_err_handler spdlog::logger::error_handler() +inline spdlog::log_err_handler spdlog::logger::error_handler() const { return err_handler_; } diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 1e5db22b..4e08076b 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -140,7 +140,7 @@ public: // error handler void set_error_handler(log_err_handler err_handler); - log_err_handler error_handler(); + log_err_handler error_handler() const; // create new logger with same sinks and configuration. virtual std::shared_ptr clone(std::string logger_name); From 121a7dcedf05084d5d12254c0d294e2121e915fd Mon Sep 17 00:00:00 2001 From: gabime Date: Wed, 24 Oct 2018 22:31:50 +0300 Subject: [PATCH 22/65] Use google benchmark to test latency --- bench/Makefile | 4 +- bench/latency.cpp | 139 ++++++++++++---------------------------------- 2 files changed, 37 insertions(+), 106 deletions(-) diff --git a/bench/Makefile b/bench/Makefile index ae23d3aa..13c3982c 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -1,5 +1,5 @@ CXX ?= g++ -CXXFLAGS = -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -I../include -fmax-errors=1 +CXXFLAGS = -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -I../include -fmax-errors=1 CXX_RELEASE_FLAGS = -Ofast -flto -Wl,--no-as-needed @@ -16,7 +16,7 @@ async_bench: async_bench.cpp latency: latency.cpp - $(CXX) latency.cpp -o latency $(CXXFLAGS) $(CXX_RELEASE_FLAGS) + $(CXX) latency.cpp -o latency $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark .PHONY: clean diff --git a/bench/latency.cpp b/bench/latency.cpp index a696276a..e2e34d1a 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -7,6 +7,8 @@ // latency.cpp : spdlog latency benchmarks // +#include "benchmark/benchmark.h" + #include "spdlog/spdlog.h" #include "spdlog/async.h" #include "spdlog/sinks/basic_file_sink.h" @@ -14,6 +16,7 @@ #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" + #include "utils.h" #include #include @@ -31,123 +34,51 @@ using namespace utils; void bench(int howmany, std::shared_ptr log); void bench_mt(int howmany, std::shared_ptr log, int thread_count); -int main(int, char *[]) +void bench_c_string(benchmark::State& state, std::shared_ptr logger) { - std::srand(static_cast(std::time(nullptr))); // use current time as seed for random generator - int howmany = 1000000; - int queue_size = howmany + 2; - int threads = 10; - size_t file_size = 30 * 1024 * 1024; - size_t rotating_files = 5; - - try - { - - cout << "******************************************************************" - "*************\n"; - cout << "Single thread\n"; - cout << "******************************************************************" - "*************\n"; - - auto basic_st = spdlog::basic_logger_mt("basic_st", "logs/basic_st.log", true); - bench(howmany, basic_st); - - auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files); - bench(howmany, rotating_st); - - auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log"); - bench(howmany, daily_st); - - bench(howmany, spdlog::create("null_st")); - - cout << "\n****************************************************************" - "***************\n"; - cout << threads << " threads sharing same logger\n"; - cout << "******************************************************************" - "*************\n"; - - auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true); - bench_mt(howmany, basic_mt, threads); - - auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files); - bench_mt(howmany, rotating_mt, threads); - - auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log"); - bench_mt(howmany, daily_mt, threads); - bench(howmany, spdlog::create("null_mt")); + const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " + "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem " + "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec fringilla dui sed " + "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare " + "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; - cout << "\n****************************************************************" - "***************\n"; - cout << "async logging.. " << threads << " threads sharing same logger\n"; - cout << "******************************************************************" - "*************\n"; - for (int i = 0; i < 3; ++i) - { - spdlog::init_thread_pool(static_cast(queue_size), 1); - auto as = spdlog::basic_logger_mt("async", "logs/basic_async.log", true); - bench_mt(howmany, as, threads); - spdlog::drop("async"); - } - } - catch (std::exception &ex) + for (auto _ : state) { - std::cerr << "Error: " << ex.what() << std::endl; - perror("Last error"); - return EXIT_FAILURE; + logger->info(msg); } - return EXIT_SUCCESS; } -void bench(int howmany, std::shared_ptr log) +void bench_formatted_int(benchmark::State& state, std::shared_ptr logger) { - using namespace std::chrono; - using chrono::high_resolution_clock; - using chrono::milliseconds; - using chrono::nanoseconds; - - cout << log->name() << "...\t\t" << flush; - nanoseconds total_nanos = nanoseconds::zero(); - for (auto i = 0; i < howmany; ++i) + + int i = 0; + for (auto _ : state) { - auto start = high_resolution_clock::now(); - log->info("Hello logger: msg number {}", i); - auto delta_nanos = chrono::duration_cast(high_resolution_clock::now() - start); - total_nanos += delta_nanos; + logger->info("Hello message {} {} {}", ++i, i , i); } - - auto avg = total_nanos.count() / howmany; - cout << format(avg) << " ns/call" << endl; } -void bench_mt(int howmany, std::shared_ptr log, int thread_count) + + + +int main(int argc, char *argv[]) { - using namespace std::chrono; - using chrono::high_resolution_clock; - using chrono::milliseconds; - using chrono::nanoseconds; - - cout << log->name() << "...\t\t" << flush; - vector threads; - std::atomic total_nanos{0}; - for (int t = 0; t < thread_count; ++t) - { - threads.push_back(std::thread([&]() { - for (int j = 0; j < howmany / thread_count; j++) - { - auto start = high_resolution_clock::now(); - log->info("Hello logger: msg number {}", j); - auto delta_nanos = chrono::duration_cast(high_resolution_clock::now() - start); - total_nanos += delta_nanos.count(); - } - })); - } - for (auto &t : threads) - { - t.join(); - }; + using spdlog::sinks::null_sink_st ; + using spdlog::sinks::null_sink_mt ; + + auto null_logger = std::make_shared("bench", std::make_shared()); + benchmark::RegisterBenchmark("null_sink_st-500_bytes_cstr", bench_c_string, null_logger); + benchmark::RegisterBenchmark("null_sink_st-formatted_int", bench_formatted_int, null_logger); + + // 10 threads + int n_threads = 10; + null_logger = std::make_shared("bench", std::make_shared()); + benchmark::RegisterBenchmark("null_sink_mt-500_bytes_cstr", bench_c_string, null_logger) -> Threads(n_threads); + benchmark::RegisterBenchmark("null_sink_mt-formatted_int", bench_formatted_int, null_logger) ->Threads(n_threads); + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); - auto avg = total_nanos / howmany; - cout << format(avg) << " ns/call" << endl; } From 47948a34dd198fecf04fd4500710ea1b22212669 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 26 Oct 2018 16:34:14 +0300 Subject: [PATCH 23/65] latency using google-benchmark --- bench/latency.cpp | 107 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/bench/latency.cpp b/bench/latency.cpp index e2e34d1a..3b74ee0e 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -15,7 +15,7 @@ #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" - +#include #include "utils.h" #include @@ -31,8 +31,32 @@ using namespace spdlog; using namespace spdlog::sinks; using namespace utils; -void bench(int howmany, std::shared_ptr log); -void bench_mt(int howmany, std::shared_ptr log, int thread_count); + +void prepare_logdir() +{ + spdlog::info("Preparing logs_bench directory.."); +#ifdef _WIN32 + system("if not exist logs mkdir logs_bench"); + system("del /F /Q logs\\*"); +#else + auto rv = system("mkdir -p logs_bench"); + if (rv != 0) + { + throw std::runtime_error("Failed to mkdir -p logs_bench"); + } + rv = system("rm -f logs_bench/*"); + if (rv != 0) + { + throw std::runtime_error("Failed to rm -f logs_bench/*"); + } +#endif +} + + +void add_rate(benchmark::State &state) +{ + state.counters["Rate"] = benchmark::Counter(1, benchmark::Counter::kIsIterationInvariantRate); +} void bench_c_string(benchmark::State& state, std::shared_ptr logger) { @@ -47,16 +71,19 @@ void bench_c_string(benchmark::State& state, std::shared_ptr log { logger->info(msg); } + add_rate(state); } -void bench_formatted_int(benchmark::State& state, std::shared_ptr logger) +void bench_logger(benchmark::State& state, std::shared_ptr logger) { - int i = 0; for (auto _ : state) { - logger->info("Hello message {} {} {}", ++i, i , i); + logger->info("Hello logger: msg number {}...............", ++i); + } + add_rate(state); + } @@ -67,17 +94,71 @@ int main(int argc, char *argv[]) using spdlog::sinks::null_sink_st ; using spdlog::sinks::null_sink_mt ; + using spdlog::sinks::basic_file_sink_st; + using spdlog::sinks::basic_file_sink_mt; + size_t file_size = 30 * 1024 * 1024; + size_t rotating_files = 5; + int n_threads = 10; + + prepare_logdir(); + + // + // Single threaded bench + // auto null_logger = std::make_shared("bench", std::make_shared()); + benchmark::RegisterBenchmark("null_sink_st-500_bytes_cstr", bench_c_string, null_logger); - benchmark::RegisterBenchmark("null_sink_st-formatted_int", bench_formatted_int, null_logger); + benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger); + benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger)->UseRealTime(); + + // basic_st + auto basic_st = spdlog::basic_logger_st("basic_st", "logs_bench/basic_st.log", true); + benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st)); + benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime(); + spdlog::drop("basic_st"); + + + // rotating st + auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs_bench/rotating_st.log", file_size, rotating_files); + benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st)); + benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))->UseRealTime(); + spdlog::drop("rotating_st"); + + + // daily st + auto daily_st = spdlog::daily_logger_mt("daily_st", "logs_bench/daily_st.log"); + benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st)); + benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime(); + spdlog::drop("daily_st"); + + // + // Multi threaded bench, 10 using same logger concurrently + // + auto null_logger_mt = std::make_shared("bench", std::make_shared()); + benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads); + benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads)->UseRealTime(); + + // basic_mt + auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs_bench/basic_mt.log", true); + benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads); + benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads)->UseRealTime(); + spdlog::drop("basic_mt"); + + + // rotating mt + auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs_bench/rotating_mt.log", file_size, rotating_files); + benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads); + benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads)->UseRealTime(); + spdlog::drop("rotating_mt"); + + + // daily mt + auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs_bench/daily_mt.log"); + benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads); + benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads)->UseRealTime(); + spdlog::drop("daily_mt"); - // 10 threads - int n_threads = 10; - null_logger = std::make_shared("bench", std::make_shared()); - benchmark::RegisterBenchmark("null_sink_mt-500_bytes_cstr", bench_c_string, null_logger) -> Threads(n_threads); - benchmark::RegisterBenchmark("null_sink_mt-formatted_int", bench_formatted_int, null_logger) ->Threads(n_threads); - benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); From f87049370fcc89feb9f0397975d087757a997916 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 26 Oct 2018 18:57:34 +0300 Subject: [PATCH 24/65] latency test update --- bench/latency.cpp | 60 ++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/bench/latency.cpp b/bench/latency.cpp index 3b74ee0e..8e8b1cec 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -52,12 +52,6 @@ void prepare_logdir() #endif } - -void add_rate(benchmark::State &state) -{ - state.counters["Rate"] = benchmark::Counter(1, benchmark::Counter::kIsIterationInvariantRate); -} - void bench_c_string(benchmark::State& state, std::shared_ptr logger) { const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " @@ -71,7 +65,7 @@ void bench_c_string(benchmark::State& state, std::shared_ptr log { logger->info(msg); } - add_rate(state); + } void bench_logger(benchmark::State& state, std::shared_ptr logger) @@ -80,10 +74,7 @@ void bench_logger(benchmark::State& state, std::shared_ptr logge for (auto _ : state) { logger->info("Hello logger: msg number {}...............", ++i); - } - add_rate(state); - } @@ -100,6 +91,7 @@ int main(int argc, char *argv[]) size_t file_size = 30 * 1024 * 1024; size_t rotating_files = 5; int n_threads = 10; + int iters = 1000000; prepare_logdir(); @@ -108,55 +100,69 @@ int main(int argc, char *argv[]) // auto null_logger = std::make_shared("bench", std::make_shared()); - benchmark::RegisterBenchmark("null_sink_st-500_bytes_cstr", bench_c_string, null_logger); - benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger); - benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger)->UseRealTime(); + benchmark::RegisterBenchmark("null_sink_st-500_bytes_cstr", bench_c_string, null_logger) + ->UseRealTime() + ->Iterations(iters); + benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger) + ->UseRealTime() + ->Iterations(iters); // basic_st auto basic_st = spdlog::basic_logger_st("basic_st", "logs_bench/basic_st.log", true); - benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st)); - benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime(); + benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st)) + ->UseRealTime() + ->Iterations(iters); spdlog::drop("basic_st"); // rotating st auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs_bench/rotating_st.log", file_size, rotating_files); - benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st)); - benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))->UseRealTime(); + benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st)) + ->UseRealTime() + ->Iterations(iters); spdlog::drop("rotating_st"); // daily st auto daily_st = spdlog::daily_logger_mt("daily_st", "logs_bench/daily_st.log"); - benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st)); - benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime(); + benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st)) + ->UseRealTime() + ->Iterations(iters); spdlog::drop("daily_st"); // // Multi threaded bench, 10 using same logger concurrently // auto null_logger_mt = std::make_shared("bench", std::make_shared()); - benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads); - benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads)->UseRealTime(); + benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt) + ->Threads(n_threads) + ->UseRealTime() + ->Iterations(iters/n_threads); // basic_mt auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs_bench/basic_mt.log", true); - benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads); - benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads)->UseRealTime(); + benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt)) + ->Threads(n_threads) + ->UseRealTime() + ->Iterations(iters/n_threads); spdlog::drop("basic_mt"); // rotating mt auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs_bench/rotating_mt.log", file_size, rotating_files); - benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads); - benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads)->UseRealTime(); + benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt)) + ->Threads(n_threads) + ->UseRealTime() + ->Iterations(iters/n_threads); spdlog::drop("rotating_mt"); // daily mt auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs_bench/daily_mt.log"); - benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads); - benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads)->UseRealTime(); + benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt)) + ->Threads(n_threads) + ->UseRealTime() + ->Iterations(iters/n_threads); spdlog::drop("daily_mt"); benchmark::Initialize(&argc, argv); From 665b708e6ed679d52db0d0ecbcc3386893f87682 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 26 Oct 2018 18:57:53 +0300 Subject: [PATCH 25/65] Update cmake --- bench/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index 5e492c0b..9c9a4365 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -38,6 +38,7 @@ add_executable(async_bench async_bench.cpp) target_link_libraries(async_bench spdlog::spdlog Threads::Threads) add_executable(latency latency.cpp) +set(CMAKE_CXX_STANDARD_LIBRARIES -lbenchmark) target_link_libraries(latency spdlog::spdlog Threads::Threads) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") From 7377bfcf07c6795e480508d43de72dd4e2c1e537 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 26 Oct 2018 18:59:00 +0300 Subject: [PATCH 26/65] Updated latency makefile --- bench/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/Makefile b/bench/Makefile index 13c3982c..83e53dc9 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -1,5 +1,5 @@ CXX ?= g++ -CXXFLAGS = -march=native -Wall -Wextra -pedantic -std=c++11 -pthread -I../include -fmax-errors=1 +CXXFLAGS = -march=native -Wall -Wextra -pedantic -Wconversion -std=c++11 -pthread -I../include -fmax-errors=1 CXX_RELEASE_FLAGS = -Ofast -flto -Wl,--no-as-needed From 1b391ccd062e013f6e0a991a3f37c3ce31eab87d Mon Sep 17 00:00:00 2001 From: Jerome Meyer Date: Mon, 29 Oct 2018 09:55:41 -0400 Subject: [PATCH 27/65] Cleanup header file: remove log_msg.h include from fmt_helper.h --- include/spdlog/details/fmt_helper.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index 21bbd154..1f716ac5 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -5,7 +5,6 @@ #pragma once #include "chrono" -#include "spdlog/details/log_msg.h" #include "spdlog/fmt/fmt.h" // Some fmt helpers to efficiently format and pad ints and strings From 7be3d2afe925986ea263a6bb18649823bf7d596c Mon Sep 17 00:00:00 2001 From: Gabi Melman Date: Mon, 29 Oct 2018 23:58:19 +0200 Subject: [PATCH 28/65] Update appveyor.yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 2a176c1b..d7843cde 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,7 +26,7 @@ build_script: set PATH=C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin;%PATH% - cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% + cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DSPDLOG_BUILD_BENCH=OFF cmake --build . --config %BUILD_TYPE% test: off From 04d577262ac5c81869be01544f5ef061520762ac Mon Sep 17 00:00:00 2001 From: gabime Date: Tue, 30 Oct 2018 00:08:49 +0200 Subject: [PATCH 29/65] Updated latency tests --- bench/latency.cpp | 127 ++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 83 deletions(-) diff --git a/bench/latency.cpp b/bench/latency.cpp index 8e8b1cec..6df593dd 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -15,44 +15,28 @@ #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/sinks/null_sink.h" #include "spdlog/sinks/rotating_file_sink.h" -#include - -#include "utils.h" -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace std::chrono; -using namespace spdlog; -using namespace spdlog::sinks; -using namespace utils; - void prepare_logdir() { - spdlog::info("Preparing logs_bench directory.."); + spdlog::info("Preparing latency_logs directory.."); #ifdef _WIN32 - system("if not exist logs mkdir logs_bench"); + system("if not exist logs mkdir latency_logs"); system("del /F /Q logs\\*"); #else - auto rv = system("mkdir -p logs_bench"); + auto rv = system("mkdir -p latency_logs"); if (rv != 0) { - throw std::runtime_error("Failed to mkdir -p logs_bench"); + throw std::runtime_error("Failed to mkdir -p latency_logs"); } - rv = system("rm -f logs_bench/*"); + rv = system("rm -f latency_logs/*"); if (rv != 0) { - throw std::runtime_error("Failed to rm -f logs_bench/*"); + throw std::runtime_error("Failed to rm -f latency_logs/*"); } #endif } -void bench_c_string(benchmark::State& state, std::shared_ptr logger) +void bench_c_string(benchmark::State &state, std::shared_ptr logger) { const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus " "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem " @@ -60,15 +44,13 @@ void bench_c_string(benchmark::State& state, std::shared_ptr log "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare " "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis."; - for (auto _ : state) { logger->info(msg); } - } -void bench_logger(benchmark::State& state, std::shared_ptr logger) +void bench_logger(benchmark::State &state, std::shared_ptr logger) { int i = 0; for (auto _ : state) @@ -77,95 +59,74 @@ void bench_logger(benchmark::State& state, std::shared_ptr logge } } - - - int main(int argc, char *argv[]) { - using spdlog::sinks::null_sink_st ; - using spdlog::sinks::null_sink_mt ; - using spdlog::sinks::basic_file_sink_st; + spdlog::set_pattern("[tid %t] %v"); using spdlog::sinks::basic_file_sink_mt; + using spdlog::sinks::basic_file_sink_st; + using spdlog::sinks::null_sink_mt; + using spdlog::sinks::null_sink_st; size_t file_size = 30 * 1024 * 1024; size_t rotating_files = 5; - int n_threads = 10; - int iters = 1000000; + int n_threads = benchmark::CPUInfo::Get().num_cpus; prepare_logdir(); - // - // Single threaded bench - // - auto null_logger = std::make_shared("bench", std::make_shared()); + // Single threaded benchmarks + auto disabled_logger = std::make_shared("bench", std::make_shared()); + disabled_logger->set_level(spdlog::level::off); + benchmark::RegisterBenchmark("disabled-level", bench_logger, disabled_logger)->UseRealTime(); + + auto null_logger_st = std::make_shared("bench", std::make_shared()); + benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st))->UseRealTime(); - benchmark::RegisterBenchmark("null_sink_st-500_bytes_cstr", bench_c_string, null_logger) - ->UseRealTime() - ->Iterations(iters); - benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger) - ->UseRealTime() - ->Iterations(iters); + benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st); // basic_st - auto basic_st = spdlog::basic_logger_st("basic_st", "logs_bench/basic_st.log", true); - benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st)) - ->UseRealTime() - ->Iterations(iters); + auto basic_st = spdlog::basic_logger_st("basic_st", "latency_logs/basic_st.log", true); + benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime(); spdlog::drop("basic_st"); - // rotating st - auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs_bench/rotating_st.log", file_size, rotating_files); - benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st)) - ->UseRealTime() - ->Iterations(iters); + auto rotating_st = spdlog::rotating_logger_st("rotating_st", "latency_logs/rotating_st.log", file_size, rotating_files); + benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))->UseRealTime(); spdlog::drop("rotating_st"); - // daily st - auto daily_st = spdlog::daily_logger_mt("daily_st", "logs_bench/daily_st.log"); - benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st)) - ->UseRealTime() - ->Iterations(iters); + auto daily_st = spdlog::daily_logger_mt("daily_st", "latency_logs/daily_st.log"); + benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime(); spdlog::drop("daily_st"); - // - // Multi threaded bench, 10 using same logger concurrently - // + // // + // // Multi threaded bench, 10 loggers using same logger concurrently + // // auto null_logger_mt = std::make_shared("bench", std::make_shared()); - benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt) - ->Threads(n_threads) - ->UseRealTime() - ->Iterations(iters/n_threads); + benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads)->UseRealTime(); // basic_mt - auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs_bench/basic_mt.log", true); - benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt)) - ->Threads(n_threads) - ->UseRealTime() - ->Iterations(iters/n_threads); + auto basic_mt = spdlog::basic_logger_mt("basic_mt", "latency_logs/basic_mt.log", true); + benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads)->UseRealTime(); spdlog::drop("basic_mt"); - // rotating mt - auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs_bench/rotating_mt.log", file_size, rotating_files); - benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt)) - ->Threads(n_threads) - ->UseRealTime() - ->Iterations(iters/n_threads); + auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "latency_logs/rotating_mt.log", file_size, rotating_files); + benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads)->UseRealTime(); spdlog::drop("rotating_mt"); - // daily mt - auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs_bench/daily_mt.log"); - benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt)) - ->Threads(n_threads) - ->UseRealTime() - ->Iterations(iters/n_threads); + auto daily_mt = spdlog::daily_logger_mt("daily_mt", "latency_logs/daily_mt.log"); + benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads)->UseRealTime(); spdlog::drop("daily_mt"); + // async + auto queue_size = 1024 * 1024 * 3; + auto tp = std::make_shared(queue_size, 1); + auto async_logger = std::make_shared( + "async_logger", std::make_shared(), std::move(tp), spdlog::async_overflow_policy::overrun_oldest); + benchmark::RegisterBenchmark("async_logger", bench_logger, async_logger)->Threads(n_threads)->UseRealTime(); + benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); - } From 5d04848886c0dfc09bfbb27e8f9c6ec20eb5b415 Mon Sep 17 00:00:00 2001 From: gabime Date: Tue, 30 Oct 2018 00:11:29 +0200 Subject: [PATCH 30/65] Updated latency Makefile --- bench/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench/Makefile b/bench/Makefile index 83e53dc9..0cec95e4 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -22,6 +22,6 @@ latency: latency.cpp .PHONY: clean clean: - rm -f *.o logs/* $(binaries) + rm -f *.o logs/* latecy_logs $(binaries) rebuild: clean all From 1b04c222cfc4781fa4e18c890e01465f9515c2dc Mon Sep 17 00:00:00 2001 From: gabime Date: Tue, 30 Oct 2018 00:54:22 +0200 Subject: [PATCH 31/65] Fixed issue #888 --- include/spdlog/details/log_msg.h | 5 ++--- include/spdlog/details/thread_pool.h | 9 +++++++-- tests/file_helper.cpp | 1 - tests/test_pattern_formatter.cpp | 12 ++++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 21f8bc6d..6244f3a9 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -15,7 +15,6 @@ namespace spdlog { namespace details { struct log_msg { - log_msg() = default; log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_t view) : logger_name(loggers_name) @@ -38,9 +37,9 @@ struct log_msg level::level_enum level{level::off}; log_clock::time_point time; size_t thread_id{0}; - size_t msg_id; + size_t msg_id{0}; - // info about wrapping the formatted text with color (updated by pattern_formatter). + // wrapping the formatted text with color (updated by pattern_formatter). mutable size_t color_range_start{0}; mutable size_t color_range_end{0}; diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index de01ad58..ec9d1788 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -82,12 +82,17 @@ struct async_msg } async_msg(async_logger_ptr &&worker, async_msg_type the_type) - : async_msg(std::move(worker), the_type, details::log_msg()) + : msg_type(the_type) + , level(level::off) + , time() + , thread_id(0) + , msg_id(0) + , worker_ptr(std::move(worker)) { } explicit async_msg(async_msg_type the_type) - : async_msg(nullptr, the_type, details::log_msg()) + : async_msg(nullptr, the_type) { } diff --git a/tests/file_helper.cpp b/tests/file_helper.cpp index bfe7eb9d..ecdc5afe 100644 --- a/tests/file_helper.cpp +++ b/tests/file_helper.cpp @@ -10,7 +10,6 @@ static const std::string target_filename = "logs/file_helper_test.txt"; static void write_with_helper(file_helper &helper, size_t howmany) { - log_msg msg; fmt::memory_buffer formatted; fmt::format_to(formatted, "{}", std::string(howmany, '1')); helper.write(formatted); diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index 8b8c9447..7b062a5d 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -75,7 +75,8 @@ TEST_CASE("color range test1", "[pattern_formatter]") TEST_CASE("color range test2", "[pattern_formatter]") { auto formatter = std::make_shared("%^%$", spdlog::pattern_time_type::local, "\n"); - spdlog::details::log_msg msg; + std::string logger_name = "test"; + spdlog::details::log_msg msg(&logger_name, spdlog::level::info, ""); fmt::memory_buffer formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); @@ -86,7 +87,8 @@ TEST_CASE("color range test2", "[pattern_formatter]") TEST_CASE("color range test3", "[pattern_formatter]") { auto formatter = std::make_shared("%^***%$"); - spdlog::details::log_msg msg; + std::string logger_name = "test"; + spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored"); fmt::memory_buffer formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); @@ -109,7 +111,8 @@ TEST_CASE("color range test4", "[pattern_formatter]") TEST_CASE("color range test5", "[pattern_formatter]") { auto formatter = std::make_shared("**%^"); - spdlog::details::log_msg msg; + std::string logger_name = "test"; + spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored"); fmt::memory_buffer formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 2); @@ -119,7 +122,8 @@ TEST_CASE("color range test5", "[pattern_formatter]") TEST_CASE("color range test6", "[pattern_formatter]") { auto formatter = std::make_shared("**%$"); - spdlog::details::log_msg msg; + std::string logger_name = "test"; + spdlog::details::log_msg msg(&logger_name, spdlog::level::info, "ignored"); fmt::memory_buffer formatted; formatter->format(msg, formatted); REQUIRE(msg.color_range_start == 0); From 80f19324bc2d4181b0f009e58e49c60a18039c18 Mon Sep 17 00:00:00 2001 From: gabime Date: Tue, 30 Oct 2018 01:08:32 +0200 Subject: [PATCH 32/65] Small update to async bench --- bench/async_bench.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bench/async_bench.cpp b/bench/async_bench.cpp index 5dd18bfa..a708797a 100644 --- a/bench/async_bench.cpp +++ b/bench/async_bench.cpp @@ -94,6 +94,7 @@ int main(int argc, char *argv[]) spdlog::info("Line count OK ({:n})\n", count); } } + spdlog::shutdown(); } catch (std::exception &ex) { @@ -101,6 +102,7 @@ int main(int argc, char *argv[]) perror("Last error"); return 1; } + return 0; } From 0d0706a2048699fbb8cd38796fef2143bbe2f549 Mon Sep 17 00:00:00 2001 From: gabime Date: Tue, 30 Oct 2018 01:14:42 +0200 Subject: [PATCH 33/65] Small fix to pattern formatter --- include/spdlog/details/pattern_formatter.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 89811d1f..17801a34 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -574,8 +574,7 @@ public: f->format(msg, cached_tm_, dest); } // write eol - // details::fmt_helper::append_string_view(eol_.c_str(), dest); - details::fmt_helper::append_string_view(eol_.c_str(), dest); + details::fmt_helper::append_string_view(eol_, dest); } private: From e35414a0f17f7b906bf32d78cc701ce169d993c3 Mon Sep 17 00:00:00 2001 From: gabime Date: Tue, 30 Oct 2018 01:23:17 +0200 Subject: [PATCH 34/65] Removed redundant casts to string_view --- include/spdlog/details/logger_impl.h | 2 +- include/spdlog/details/pattern_formatter.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index e7385b5d..850f8639 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -96,7 +96,7 @@ inline void spdlog::logger::log(level::level_enum lvl, const T &msg) } try { - details::log_msg log_msg(&name_, lvl, static_cast(msg)); + details::log_msg log_msg(&name_, lvl, msg); sink_it_(log_msg); } SPDLOG_CATCH_AND_HANDLE diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 17801a34..36174172 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -38,7 +38,7 @@ class name_formatter : public flag_formatter { void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(string_view_t(*msg.logger_name), dest); + fmt_helper::append_string_view(*msg.logger_name, dest); } }; From 794a636dd3cebd59e49ef3a0bfaf8bfffc729bdd Mon Sep 17 00:00:00 2001 From: rwen2012 Date: Wed, 31 Oct 2018 11:01:28 +0800 Subject: [PATCH 35/65] change the log_msg&& to log_msg& --- include/spdlog/details/async_logger_impl.h | 2 +- include/spdlog/details/thread_pool.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/spdlog/details/async_logger_impl.h b/include/spdlog/details/async_logger_impl.h index 2841ab2b..aafcae65 100644 --- a/include/spdlog/details/async_logger_impl.h +++ b/include/spdlog/details/async_logger_impl.h @@ -43,7 +43,7 @@ inline void spdlog::async_logger::sink_it_(details::log_msg &msg) #endif if (auto pool_ptr = thread_pool_.lock()) { - pool_ptr->post_log(shared_from_this(), std::move(msg), overflow_policy_); + pool_ptr->post_log(shared_from_this(), msg, overflow_policy_); } else { diff --git a/include/spdlog/details/thread_pool.h b/include/spdlog/details/thread_pool.h index ec9d1788..a1c07d3f 100644 --- a/include/spdlog/details/thread_pool.h +++ b/include/spdlog/details/thread_pool.h @@ -70,7 +70,7 @@ struct async_msg #endif // construct from log_msg with given type - async_msg(async_logger_ptr &&worker, async_msg_type the_type, details::log_msg &&m) + async_msg(async_logger_ptr &&worker, async_msg_type the_type, details::log_msg &m) : msg_type(the_type) , level(m.level) , time(m.time) @@ -154,9 +154,9 @@ public: thread_pool(const thread_pool &) = delete; thread_pool &operator=(thread_pool &&) = delete; - void post_log(async_logger_ptr &&worker_ptr, details::log_msg &&msg, async_overflow_policy overflow_policy) + void post_log(async_logger_ptr &&worker_ptr, details::log_msg &msg, async_overflow_policy overflow_policy) { - async_msg async_m(std::move(worker_ptr), async_msg_type::log, std::move(msg)); + async_msg async_m(std::move(worker_ptr), async_msg_type::log, msg); post_async_msg_(std::move(async_m), overflow_policy); } From 1aace95c8d14944358c0374bbda3ce44d759bef7 Mon Sep 17 00:00:00 2001 From: Gabi Melman Date: Fri, 2 Nov 2018 17:53:27 +0200 Subject: [PATCH 36/65] Update periodic_worker.h --- include/spdlog/details/periodic_worker.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/spdlog/details/periodic_worker.h b/include/spdlog/details/periodic_worker.h index 57e5fa77..fa6488d1 100644 --- a/include/spdlog/details/periodic_worker.h +++ b/include/spdlog/details/periodic_worker.h @@ -10,7 +10,7 @@ // // RAII over the owned thread: // creates the thread on construction. -// stops and joins the thread on destruction. +// stops and joins the thread on destruction (if the thread is executing a callback, wait for it to finish first). #include #include From f95b189fe3fb96f11e308325c37499b8f7e921c5 Mon Sep 17 00:00:00 2001 From: Pablo Arias Date: Sun, 4 Nov 2018 20:12:42 +0100 Subject: [PATCH 37/65] Added a global option in tweakme.h that disabled global registration of loggers. fixes #712 --- include/spdlog/async.h | 5 ++++- include/spdlog/details/registry.h | 10 +--------- include/spdlog/spdlog.h | 5 ++++- include/spdlog/tweakme.h | 8 ++++++++ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/spdlog/async.h b/include/spdlog/async.h index 9264a4e3..bf7dee46 100644 --- a/include/spdlog/async.h +++ b/include/spdlog/async.h @@ -52,7 +52,10 @@ struct async_factory_impl auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy); - registry_inst.register_and_init(new_logger); + registry_inst.init_with_global_defaults(new_logger); +#ifndef SPDLOG_DISABLE_GLOBAL_REGISTRATION + registry_inst.register_logger(new_logger); +#endif return new_logger; } }; diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 439395f7..8f7e7f01 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -47,13 +47,8 @@ public: loggers_[logger_name] = std::move(new_logger); } - void register_and_init(std::shared_ptr new_logger) + void init_with_global_defaults(std::shared_ptr new_logger) { - std::lock_guard lock(logger_map_mutex_); - auto logger_name = new_logger->name(); - throw_if_exists_(logger_name); - - // set the global formatter pattern new_logger->set_formatter(formatter_->clone()); if (err_handler_) @@ -63,9 +58,6 @@ public: new_logger->set_level(level_); new_logger->flush_on(flush_level_); - - // add to registry - loggers_[logger_name] = std::move(new_logger); } std::shared_ptr get(const std::string &logger_name) diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index bcca2e84..d2d8a194 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -29,7 +29,10 @@ struct synchronous_factory { auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); - details::registry::instance().register_and_init(new_logger); + details::registry::instance().init_with_global_defaults(new_logger); +#ifndef SPDLOG_DISABLE_GLOBAL_REGISTRATION + details::registry::instance().register_logger(new_logger); +#endif return new_logger; } }; diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h index d91159f7..a18593c4 100644 --- a/include/spdlog/tweakme.h +++ b/include/spdlog/tweakme.h @@ -128,3 +128,11 @@ // // #define SPDLOG_DISABLE_DEFAULT_LOGGER /////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment to disable global logger registration +// This is useful if you don't need loggers to be globally accessible and part of the global registry. +// This option will allow you to use the same name for different loggers. +// +// #define SPDLOG_DISABLE_GLOBAL_REGISTRATION +/////////////////////////////////////////////////////////////////////////////// From f5a27250b1c701bb3317fa2ad6332fd893f26ab1 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Mon, 5 Nov 2018 03:04:22 +0300 Subject: [PATCH 38/65] Fix typo in Android example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 37eb997d..8e85b9d6 100644 --- a/README.md +++ b/README.md @@ -305,7 +305,7 @@ void syslog_example() --- #### Android example ```c++ -#incude "spdlog/sinks/android_sink.h" +#include "spdlog/sinks/android_sink.h" void android_example() { std::string tag = "spdlog-android"; From 4df28728e2602f1e82444509aa94afa6024921a0 Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 9 Nov 2018 14:56:48 +0200 Subject: [PATCH 39/65] clang-format --- include/spdlog/sinks/rotating_file_sink.h | 308 +++++++++++----------- 1 file changed, 154 insertions(+), 154 deletions(-) diff --git a/include/spdlog/sinks/rotating_file_sink.h b/include/spdlog/sinks/rotating_file_sink.h index adf12b6f..14fd0bb6 100644 --- a/include/spdlog/sinks/rotating_file_sink.h +++ b/include/spdlog/sinks/rotating_file_sink.h @@ -1,154 +1,154 @@ -// -// Copyright(c) 2015 Gabi Melman. -// Distributed under the MIT License (http://opensource.org/licenses/MIT) -// - -#pragma once - -#ifndef SPDLOG_H -#error "spdlog.h must be included before this file." -#endif - -#include "spdlog/details/file_helper.h" -#include "spdlog/details/null_mutex.h" -#include "spdlog/fmt/fmt.h" -#include "spdlog/sinks/base_sink.h" - -#include -#include -#include -#include -#include -#include - -namespace spdlog { -namespace sinks { - -// -// Rotating file sink based on size -// -template -class rotating_file_sink final : public base_sink -{ -public: - rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files) - : base_filename_(std::move(base_filename)) - , max_size_(max_size) - , max_files_(max_files) - { - file_helper_.open(calc_filename(base_filename_, 0)); - current_size_ = file_helper_.size(); // expensive. called only once - } - - // calc filename according to index and file extension if exists. - // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". - static filename_t calc_filename(const filename_t &filename, std::size_t index) - { - typename std::conditional::value, fmt::memory_buffer, fmt::wmemory_buffer>::type w; - if (index != 0u) - { - filename_t basename, ext; - std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); - fmt::format_to(w, SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); - } - else - { - fmt::format_to(w, SPDLOG_FILENAME_T("{}"), filename); - } - return fmt::to_string(w); - } - -protected: - void sink_it_(const details::log_msg &msg) override - { - fmt::memory_buffer formatted; - sink::formatter_->format(msg, formatted); - current_size_ += formatted.size(); - if (current_size_ > max_size_) - { - rotate_(); - current_size_ = formatted.size(); - } - file_helper_.write(formatted); - } - - void flush_() override - { - file_helper_.flush(); - } - -private: - // Rotate files: - // log.txt -> log.1.txt - // log.1.txt -> log.2.txt - // log.2.txt -> log.3.txt - // log.3.txt -> delete - void rotate_() - { - using details::os::filename_to_str; - file_helper_.close(); - for (auto i = max_files_; i > 0; --i) - { - filename_t src = calc_filename(base_filename_, i - 1); - if (!details::file_helper::file_exists(src)) - { - continue; - } - filename_t target = calc_filename(base_filename_, i); - - if (!rename_file(src, target)) - { - // if failed try again after a small delay. - // this is a workaround to a windows issue, where very high rotation - // rates can cause the rename to fail with permission denied (because of antivirus?). - details::os::sleep_for_millis(100); - if (!rename_file(src, target)) - { - file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit! - throw spdlog_ex( - "rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); - } - } - } - file_helper_.reopen(true); - } - - // delete the target if exists, and rename the src file to target - // return true on success, false otherwise. - bool rename_file(const filename_t &src_filename, const filename_t &target_filename) - { - // try to delete the target file in case it already exists. - (void)details::os::remove(target_filename); - return details::os::rename(src_filename, target_filename) == 0; - } - - filename_t base_filename_; - std::size_t max_size_; - std::size_t max_files_; - std::size_t current_size_; - details::file_helper file_helper_; -}; - -using rotating_file_sink_mt = rotating_file_sink; -using rotating_file_sink_st = rotating_file_sink; - -} // namespace sinks - -// -// factory functions -// - -template -inline std::shared_ptr rotating_logger_mt( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) -{ - return Factory::template create(logger_name, filename, max_file_size, max_files); -} - -template -inline std::shared_ptr rotating_logger_st( - const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) -{ - return Factory::template create(logger_name, filename, max_file_size, max_files); -} -} // namespace spdlog +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#ifndef SPDLOG_H +#error "spdlog.h must be included before this file." +#endif + +#include "spdlog/details/file_helper.h" +#include "spdlog/details/null_mutex.h" +#include "spdlog/fmt/fmt.h" +#include "spdlog/sinks/base_sink.h" + +#include +#include +#include +#include +#include +#include + +namespace spdlog { +namespace sinks { + +// +// Rotating file sink based on size +// +template +class rotating_file_sink final : public base_sink +{ +public: + rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files) + : base_filename_(std::move(base_filename)) + , max_size_(max_size) + , max_files_(max_files) + { + file_helper_.open(calc_filename(base_filename_, 0)); + current_size_ = file_helper_.size(); // expensive. called only once + } + + // calc filename according to index and file extension if exists. + // e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt". + static filename_t calc_filename(const filename_t &filename, std::size_t index) + { + typename std::conditional::value, fmt::memory_buffer, fmt::wmemory_buffer>::type w; + if (index != 0u) + { + filename_t basename, ext; + std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename); + fmt::format_to(w, SPDLOG_FILENAME_T("{}.{}{}"), basename, index, ext); + } + else + { + fmt::format_to(w, SPDLOG_FILENAME_T("{}"), filename); + } + return fmt::to_string(w); + } + +protected: + void sink_it_(const details::log_msg &msg) override + { + fmt::memory_buffer formatted; + sink::formatter_->format(msg, formatted); + current_size_ += formatted.size(); + if (current_size_ > max_size_) + { + rotate_(); + current_size_ = formatted.size(); + } + file_helper_.write(formatted); + } + + void flush_() override + { + file_helper_.flush(); + } + +private: + // Rotate files: + // log.txt -> log.1.txt + // log.1.txt -> log.2.txt + // log.2.txt -> log.3.txt + // log.3.txt -> delete + void rotate_() + { + using details::os::filename_to_str; + file_helper_.close(); + for (auto i = max_files_; i > 0; --i) + { + filename_t src = calc_filename(base_filename_, i - 1); + if (!details::file_helper::file_exists(src)) + { + continue; + } + filename_t target = calc_filename(base_filename_, i); + + if (!rename_file(src, target)) + { + // if failed try again after a small delay. + // this is a workaround to a windows issue, where very high rotation + // rates can cause the rename to fail with permission denied (because of antivirus?). + details::os::sleep_for_millis(100); + if (!rename_file(src, target)) + { + file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit! + throw spdlog_ex( + "rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno); + } + } + } + file_helper_.reopen(true); + } + + // delete the target if exists, and rename the src file to target + // return true on success, false otherwise. + bool rename_file(const filename_t &src_filename, const filename_t &target_filename) + { + // try to delete the target file in case it already exists. + (void)details::os::remove(target_filename); + return details::os::rename(src_filename, target_filename) == 0; + } + + filename_t base_filename_; + std::size_t max_size_; + std::size_t max_files_; + std::size_t current_size_; + details::file_helper file_helper_; +}; + +using rotating_file_sink_mt = rotating_file_sink; +using rotating_file_sink_st = rotating_file_sink; + +} // namespace sinks + +// +// factory functions +// + +template +inline std::shared_ptr rotating_logger_mt( + const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) +{ + return Factory::template create(logger_name, filename, max_file_size, max_files); +} + +template +inline std::shared_ptr rotating_logger_st( + const std::string &logger_name, const filename_t &filename, size_t max_file_size, size_t max_files) +{ + return Factory::template create(logger_name, filename, max_file_size, max_files); +} +} // namespace spdlog From 5c54414be70a56602b5a7d644502648f917685cd Mon Sep 17 00:00:00 2001 From: gabime Date: Fri, 9 Nov 2018 15:18:45 +0200 Subject: [PATCH 40/65] Padding support in pattern formatter --- include/spdlog/details/pattern_formatter.h | 465 ++++++++++++++++++--- 1 file changed, 415 insertions(+), 50 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 36174172..6ee78c58 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -24,11 +25,92 @@ namespace spdlog { namespace details { +struct padding_info +{ + enum pad_side + { + left, + right, + center + }; + + padding_info() = default; + padding_info(size_t width, padding_info::pad_side side) + : width_(width) + , side_(side) + { + } + const size_t width_ = 0; + const pad_side side_ = left; + const char fill_ = '.'; +}; + +class scoped_pad +{ +public: + scoped_pad(size_t text_size, padding_info &padinfo, fmt::memory_buffer &dest) + : text_size_(text_size) + , padinfo_(padinfo) + , dest_(dest) + { + // if (padinfo_.pad_left_) + if (padinfo_.side_ == padding_info::left || padinfo_.side_ == padding_info::center) + { + pad(true); + } + } + + scoped_pad(spdlog::string_view_t txt, padding_info &padinfo, fmt::memory_buffer &dest) + : scoped_pad(txt.size(), padinfo, dest) + { + } + + ~scoped_pad() + { + if (padinfo_.side_ == padding_info::right || padinfo_.side_ == padding_info::center) + { + pad(false); + } + } + +private: + void pad(bool is_left_side) + { + if (padinfo_.width_ <= text_size_) + { + return; + } + + auto howmany = padinfo_.width_ - text_size_; + if (padinfo_.side_ == padding_info::center) + { + auto reminder = is_left_side ? howmany % 2 : 0; + howmany = (howmany / 2) + reminder; + } + for (size_t i = 0; i < howmany; i++) + { + dest_.push_back(padinfo_.fill_); + } + } + + const size_t text_size_; + const padding_info &padinfo_; + fmt::memory_buffer &dest_; +}; + class flag_formatter { public: + explicit flag_formatter(padding_info padinfo) + : padinfo_(padinfo) + { + } + flag_formatter() = default; virtual ~flag_formatter() = default; virtual void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) = 0; + +protected: + padding_info padinfo_; }; /////////////////////////////////////////////////////////////////////// @@ -36,8 +118,15 @@ public: /////////////////////////////////////////////////////////////////////// class name_formatter : public flag_formatter { +public: + explicit name_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + scoped_pad p(*msg.logger_name, padinfo_, dest); fmt_helper::append_string_view(*msg.logger_name, dest); } }; @@ -45,18 +134,34 @@ class name_formatter : public flag_formatter // log level appender class level_formatter : public flag_formatter { +public: + explicit level_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(level::to_c_str(msg.level), dest); + string_view_t level_name{level::to_c_str(msg.level)}; + scoped_pad p(level_name, padinfo_, dest); + fmt_helper::append_string_view(level_name, dest); } }; // short log level appender class short_level_formatter : public flag_formatter { +public: + explicit short_level_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(level::to_short_c_str(msg.level), dest); + string_view_t level_name{level::to_short_c_str(msg.level)}; + scoped_pad p(level_name, padinfo_, dest); + fmt_helper::append_string_view(level_name, dest); } }; @@ -78,9 +183,17 @@ static int to12h(const tm &t) static const char *days[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; class a_formatter : public flag_formatter { +public: + explicit a_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(days[tm_time.tm_wday], dest); + string_view_t field_value{days[tm_time.tm_wday]}; + scoped_pad p(field_value, padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); } }; @@ -88,9 +201,17 @@ class a_formatter : public flag_formatter static const char *full_days[]{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; class A_formatter : public flag_formatter { +public: + explicit A_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(full_days[tm_time.tm_wday], dest); + string_view_t field_value{full_days[tm_time.tm_wday]}; + scoped_pad p(field_value, padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); } }; @@ -98,9 +219,17 @@ class A_formatter : public flag_formatter static const char *months[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}; class b_formatter : public flag_formatter { +public: + explicit b_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(months[tm_time.tm_mon], dest); + string_view_t field_value{months[tm_time.tm_mon]}; + scoped_pad p(field_value, padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); } }; @@ -109,20 +238,34 @@ static const char *full_months[]{ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; class B_formatter : public flag_formatter { +public: + explicit B_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - fmt_helper::append_string_view(full_months[tm_time.tm_mon], dest); + string_view_t field_value{full_months[tm_time.tm_mon]}; + scoped_pad p(field_value, padinfo_, dest); + fmt_helper::append_string_view(field_value, dest); } }; // Date and time representation (Thu Aug 23 15:35:46 2014) class c_formatter final : public flag_formatter { +public: + explicit c_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - // fmt::format_to(dest, "{} {} {} ", days[tm_time.tm_wday], - // months[tm_time.tm_mon], tm_time.tm_mday); - // date + const size_t field_size = 24; + scoped_pad p(field_size, padinfo_, dest); + fmt_helper::append_string_view(days[tm_time.tm_wday], dest); dest.push_back(' '); fmt_helper::append_string_view(months[tm_time.tm_mon], dest); @@ -144,8 +287,16 @@ class c_formatter final : public flag_formatter // year - 2 digit class C_formatter final : public flag_formatter { +public: + explicit C_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(tm_time.tm_year % 100, dest); } }; @@ -153,8 +304,17 @@ class C_formatter final : public flag_formatter // Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 class D_formatter final : public flag_formatter { +public: + explicit D_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 10; + scoped_pad p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_mon + 1, dest); dest.push_back('/'); fmt_helper::pad2(tm_time.tm_mday, dest); @@ -166,8 +326,14 @@ class D_formatter final : public flag_formatter // year - 4 digit class Y_formatter final : public flag_formatter { +public: + explicit Y_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 4; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::append_int(tm_time.tm_year + 1900, dest); } }; @@ -175,8 +341,16 @@ class Y_formatter final : public flag_formatter // month 1-12 class m_formatter final : public flag_formatter { +public: + explicit m_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(tm_time.tm_mon + 1, dest); } }; @@ -184,8 +358,16 @@ class m_formatter final : public flag_formatter // day of month 1-31 class d_formatter final : public flag_formatter { +public: + explicit d_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(tm_time.tm_mday, dest); } }; @@ -193,8 +375,16 @@ class d_formatter final : public flag_formatter // hours in 24 format 0-23 class H_formatter final : public flag_formatter { +public: + explicit H_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(tm_time.tm_hour, dest); } }; @@ -202,8 +392,14 @@ class H_formatter final : public flag_formatter // hours in 12 format 1-12 class I_formatter final : public flag_formatter { +public: + explicit I_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(to12h(tm_time), dest); } }; @@ -211,8 +407,14 @@ class I_formatter final : public flag_formatter // minutes 0-59 class M_formatter final : public flag_formatter { +public: + explicit M_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(tm_time.tm_min, dest); } }; @@ -220,8 +422,14 @@ class M_formatter final : public flag_formatter // seconds 0-59 class S_formatter final : public flag_formatter { +public: + explicit S_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad2(tm_time.tm_sec, dest); } }; @@ -229,8 +437,15 @@ class S_formatter final : public flag_formatter // milliseconds class e_formatter final : public flag_formatter { +public: + explicit e_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 3; + scoped_pad p(field_size, padinfo_, dest); + auto millis = fmt_helper::time_fraction(msg.time); fmt_helper::pad3(static_cast(millis.count()), dest); } @@ -239,8 +454,15 @@ class e_formatter final : public flag_formatter // microseconds class f_formatter final : public flag_formatter { +public: + explicit f_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 6; + scoped_pad p(field_size, padinfo_, dest); + auto micros = fmt_helper::time_fraction(msg.time); fmt_helper::pad6(static_cast(micros.count()), dest); } @@ -249,8 +471,15 @@ class f_formatter final : public flag_formatter // nanoseconds class F_formatter final : public flag_formatter { +public: + explicit F_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 9; + scoped_pad p(field_size, padinfo_, dest); + auto ns = fmt_helper::time_fraction(msg.time); fmt::format_to(dest, "{:09}", ns.count()); } @@ -259,8 +488,15 @@ class F_formatter final : public flag_formatter // seconds since epoch class E_formatter final : public flag_formatter { +public: + explicit E_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 10; + scoped_pad p(field_size, padinfo_, dest); + auto duration = msg.time.time_since_epoch(); auto seconds = std::chrono::duration_cast(duration).count(); fmt_helper::append_int(seconds, dest); @@ -270,8 +506,14 @@ class E_formatter final : public flag_formatter // AM/PM class p_formatter final : public flag_formatter { +public: + explicit p_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 2; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::append_string_view(ampm(tm_time), dest); } }; @@ -279,8 +521,15 @@ class p_formatter final : public flag_formatter // 12 hour clock 02:55:02 pm class r_formatter final : public flag_formatter { +public: + explicit r_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 11; + scoped_pad p(field_size, padinfo_, dest); + fmt_helper::pad2(to12h(tm_time), dest); dest.push_back(':'); fmt_helper::pad2(tm_time.tm_min, dest); @@ -294,8 +543,15 @@ class r_formatter final : public flag_formatter // 24-hour HH:MM time, equivalent to %H:%M class R_formatter final : public flag_formatter { +public: + explicit R_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 5; + scoped_pad p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_hour, dest); dest.push_back(':'); fmt_helper::pad2(tm_time.tm_min, dest); @@ -305,10 +561,16 @@ class R_formatter final : public flag_formatter // ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S class T_formatter final : public flag_formatter { +public: + explicit T_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &tm_time, fmt::memory_buffer &dest) override { - // fmt::format_to(dest, "{:02}:{:02}:{:02}", tm_time.tm_hour, - // tm_time.tm_min, tm_time.tm_sec); + + const size_t field_size = 8; + scoped_pad p(field_size, padinfo_, dest); + fmt_helper::pad2(tm_time.tm_hour, dest); dest.push_back(':'); fmt_helper::pad2(tm_time.tm_min, dest); @@ -321,6 +583,9 @@ class T_formatter final : public flag_formatter class z_formatter final : public flag_formatter { public: + explicit z_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + const std::chrono::seconds cache_refresh = std::chrono::seconds(5); z_formatter() = default; @@ -329,6 +594,9 @@ public: void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override { + const size_t field_size = 6; + scoped_pad p(field_size, padinfo_, dest); + #ifdef _WIN32 int total_minutes = get_cached_offset(msg, tm_time); #else @@ -373,8 +641,14 @@ private: // Thread id class t_formatter final : public flag_formatter { +public: + explicit t_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 6; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad6(msg.thread_id, dest); } }; @@ -382,38 +656,59 @@ class t_formatter final : public flag_formatter // Current pid class pid_formatter final : public flag_formatter { +public: + explicit pid_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override { - fmt_helper::append_int(details::os::pid(), dest); + const size_t field_size = 6; + scoped_pad p(field_size, padinfo_, dest); + fmt_helper::pad6(details::os::pid(), dest); } }; // message counter formatter class i_formatter final : public flag_formatter { +public: + explicit i_formatter(padding_info padinfo) + : flag_formatter(padinfo){}; + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 6; + scoped_pad p(field_size, padinfo_, dest); fmt_helper::pad6(msg.msg_id, dest); } }; 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 &, fmt::memory_buffer &dest) override { + scoped_pad p(msg.payload, padinfo_, dest); fmt_helper::append_string_view(msg.payload, dest); } }; class ch_formatter final : public flag_formatter { +public: public: explicit ch_formatter(char ch) : ch_(ch) { } + void format(const details::log_msg &, const std::tm &, fmt::memory_buffer &dest) override { + const size_t field_size = 1; + scoped_pad p(field_size, padinfo_, dest); dest.push_back(ch_); } @@ -443,6 +738,12 @@ private: // mark the color range. expect it to be in the form of "%^colored text%$" class color_start_formatter final : public flag_formatter { +public: + explicit color_start_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { msg.color_range_start = dest.size(); @@ -450,6 +751,12 @@ class color_start_formatter final : public flag_formatter }; class color_stop_formatter final : public flag_formatter { +public: + explicit color_stop_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &msg, const std::tm &, fmt::memory_buffer &dest) override { msg.color_range_end = dest.size(); @@ -460,6 +767,12 @@ class color_stop_formatter final : public flag_formatter // pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v class full_formatter final : public flag_formatter { +public: + explicit full_formatter(padding_info padinfo) + : flag_formatter(padinfo) + { + } + void format(const details::log_msg &msg, const std::tm &tm_time, fmt::memory_buffer &dest) override { using std::chrono::duration_cast; @@ -595,151 +908,200 @@ private: return details::os::gmtime(log_clock::to_time_t(msg.time)); } - void handle_flag_(char flag) + void handle_flag_(char flag, details::padding_info padding) { switch (flag) { // logger name case 'n': - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case 'l': - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case 'L': - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('t'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('v'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('a'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('A'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('b'): case ('h'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('B'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('c'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('C'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('Y'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('D'): case ('x'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('m'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('d'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('H'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('I'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('M'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('S'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('e'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('f'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('F'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('E'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('p'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('r'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('R'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('T'): case ('X'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('z'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('+'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('P'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; #ifdef SPDLOG_ENABLE_MESSAGE_COUNTER case ('i'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; #endif case ('^'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; case ('$'): - formatters_.push_back(details::make_unique()); + formatters_.push_back(details::make_unique(padding)); break; - default: // Unknown flag appears as is + case ('%'): formatters_.push_back(details::make_unique('%')); - formatters_.push_back(details::make_unique(flag)); + break; + + default: // Unknown flag appears as is + auto unknown_flag = details::make_unique(); + unknown_flag->add_ch('%'); + unknown_flag->add_ch(flag); + formatters_.push_back((std::move(unknown_flag))); break; } } + // Extract given pad spec (e.g. %8X) + // Advance the given it pass the end of the padding spec found (if any) + // Return padding. + details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end) + { + using details::padding_info; + const size_t max_width = 4096; + + if (it == end) + { + return padding_info(); + } + + padding_info::pad_side side; + switch (*it) + { + case '-': + side = padding_info::right; + ++it; + break; + case '=': + side = padding_info::center; + ++it; + break; + default: + side = details::padding_info::left; + break; + } + + if (it == end || !std::isdigit(static_cast(*it))) + { + return padding_info(0, side); + } + + size_t width = static_cast(*it - '0'); + for (++it; it != end && std::isdigit(static_cast(*it)); ++it) + { + auto digit = static_cast(*it - '0'); + width = width * 10 + digit; + } + return details::padding_info{std::min(width, max_width), side}; + } + void compile_pattern_(const std::string &pattern) { auto end = pattern.end(); @@ -753,9 +1115,12 @@ private: { formatters_.push_back(std::move(user_chars)); } - if (++it != end) + + auto padding = handle_padspec_(++it, end); + + if (it != end) { - handle_flag_(*it); + handle_flag_(*it, padding); } else { From fbc58ebef82b6aa95b10f11e9ef2e69df255e022 Mon Sep 17 00:00:00 2001 From: Pablo Arias Date: Sat, 10 Nov 2018 14:34:04 +0100 Subject: [PATCH 41/65] * using API call instead of macro for toggling automatic registration * added unit test for disabling automatic registration --- include/spdlog/async.h | 5 +---- include/spdlog/details/registry.h | 13 ++++++++++++- include/spdlog/spdlog.h | 11 +++++++---- include/spdlog/tweakme.h | 8 -------- tests/test_registry.cpp | 17 +++++++++++++++++ 5 files changed, 37 insertions(+), 17 deletions(-) diff --git a/include/spdlog/async.h b/include/spdlog/async.h index bf7dee46..971becd7 100644 --- a/include/spdlog/async.h +++ b/include/spdlog/async.h @@ -52,10 +52,7 @@ struct async_factory_impl auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy); - registry_inst.init_with_global_defaults(new_logger); -#ifndef SPDLOG_DISABLE_GLOBAL_REGISTRATION - registry_inst.register_logger(new_logger); -#endif + registry_inst.initialize_logger(new_logger); return new_logger; } }; diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 8f7e7f01..f6bfe0bd 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -47,7 +47,7 @@ public: loggers_[logger_name] = std::move(new_logger); } - void init_with_global_defaults(std::shared_ptr new_logger) + void initialize_logger(std::shared_ptr new_logger) { new_logger->set_formatter(formatter_->clone()); @@ -58,6 +58,11 @@ public: new_logger->set_level(level_); new_logger->flush_on(flush_level_); + + if (automatic_registration_) + { + register_logger(new_logger); + } } std::shared_ptr get(const std::string &logger_name) @@ -215,6 +220,11 @@ public: return tp_mutex_; } + void set_automatic_registration(bool automatic_regsistration) + { + automatic_registration_ = automatic_regsistration; + } + static registry &instance() { static registry s_instance; @@ -261,6 +271,7 @@ private: std::shared_ptr tp_; std::unique_ptr periodic_flusher_; std::shared_ptr default_logger_; + bool automatic_registration_ = true; }; } // namespace details diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index d2d8a194..8c07012e 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -29,10 +29,7 @@ struct synchronous_factory { auto sink = std::make_shared(std::forward(args)...); auto new_logger = std::make_shared(std::move(logger_name), std::move(sink)); - details::registry::instance().init_with_global_defaults(new_logger); -#ifndef SPDLOG_DISABLE_GLOBAL_REGISTRATION - details::registry::instance().register_logger(new_logger); -#endif + details::registry::instance().initialize_logger(new_logger); return new_logger; } }; @@ -128,6 +125,12 @@ inline void shutdown() details::registry::instance().shutdown(); } +// Automatic registration of loggers when using spdlog::create() or spdlog::create_async +inline void set_automatic_registration(bool automatic_registation) +{ + details::registry::instance().set_automatic_registration(automatic_registation); +} + // API for using default logger (stdout_color_mt), // e.g: spdlog::info("Message {}", 1); // diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h index a18593c4..d91159f7 100644 --- a/include/spdlog/tweakme.h +++ b/include/spdlog/tweakme.h @@ -128,11 +128,3 @@ // // #define SPDLOG_DISABLE_DEFAULT_LOGGER /////////////////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -// Uncomment to disable global logger registration -// This is useful if you don't need loggers to be globally accessible and part of the global registry. -// This option will allow you to use the same name for different loggers. -// -// #define SPDLOG_DISABLE_GLOBAL_REGISTRATION -/////////////////////////////////////////////////////////////////////////////// diff --git a/tests/test_registry.cpp b/tests/test_registry.cpp index 68833012..57976083 100644 --- a/tests/test_registry.cpp +++ b/tests/test_registry.cpp @@ -93,3 +93,20 @@ TEST_CASE("set_default_logger(nullptr)", "[registry]") spdlog::set_default_logger(nullptr); REQUIRE_FALSE(spdlog::default_logger()); } + +TEST_CASE("disable automatic registration", "[registry]") +{ + // set some global parameters + spdlog::level::level_enum log_level = spdlog::level::level_enum::warn; + spdlog::set_level(log_level); + // but disable automatic registration + spdlog::set_automatic_registration(false); + auto logger1 = spdlog::create(tested_logger_name, "filename", 11, 59); + auto logger2 = spdlog::create_async(tested_logger_name2); + // loggers should not be part of the registry + REQUIRE_FALSE(spdlog::get(tested_logger_name)); + REQUIRE_FALSE(spdlog::get(tested_logger_name2)); + // but make sure they are still initialized according to global defaults + REQUIRE(logger1->level() == log_level); + REQUIRE(logger2->level() == log_level); +} From 10895796b240113416b4bc5bd30002bea8601aaf Mon Sep 17 00:00:00 2001 From: Pablo Arias Date: Sat, 10 Nov 2018 16:55:35 +0100 Subject: [PATCH 42/65] Added mutexes to protect logger initialization and toggling automatic registration --- include/spdlog/details/registry.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index f6bfe0bd..e22b8bbc 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -49,6 +49,7 @@ public: void initialize_logger(std::shared_ptr new_logger) { + std::lock_guard lock(logger_map_mutex_); new_logger->set_formatter(formatter_->clone()); if (err_handler_) @@ -222,6 +223,7 @@ public: void set_automatic_registration(bool automatic_regsistration) { + std::lock_guard lock(logger_map_mutex_); automatic_registration_ = automatic_regsistration; } From 3ff541cf775954cd261e96a1e7e439d4b2fa4d0d Mon Sep 17 00:00:00 2001 From: gabime Date: Sat, 10 Nov 2018 18:03:11 +0200 Subject: [PATCH 43/65] Optimized scoped_pad --- include/spdlog/details/pattern_formatter.h | 69 ++++++++++++++-------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 6ee78c58..f28eb3cd 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -25,6 +25,7 @@ namespace spdlog { namespace details { +// padding information. struct padding_info { enum pad_side @@ -42,21 +43,36 @@ struct padding_info } const size_t width_ = 0; const pad_side side_ = left; - const char fill_ = '.'; }; class scoped_pad { public: - scoped_pad(size_t text_size, padding_info &padinfo, fmt::memory_buffer &dest) - : text_size_(text_size) - , padinfo_(padinfo) + + static const size_t max_width = 128; + + scoped_pad(size_t wrapped_size, padding_info &padinfo, fmt::memory_buffer &dest): + padinfo_(padinfo) , dest_(dest) + , nchars_(padinfo_.width_ > wrapped_size ? padinfo_.width_ - wrapped_size : 0) { - // if (padinfo_.pad_left_) - if (padinfo_.side_ == padding_info::left || padinfo_.side_ == padding_info::center) + + if(nchars_ == 0) + { + return; + } + + if (padinfo_.side_ == padding_info::left) + { + pad_it(nchars_); + nchars_ = 0; + return; + } + else if(padinfo_.side_ == padding_info::center) { - pad(true); + + pad_it(nchars_/ 2); + return; } } @@ -67,35 +83,36 @@ public: ~scoped_pad() { - if (padinfo_.side_ == padding_info::right || padinfo_.side_ == padding_info::center) - { - pad(false); - } - } -private: - void pad(bool is_left_side) - { - if (padinfo_.width_ <= text_size_) + if(nchars_ == 0) { return; } - auto howmany = padinfo_.width_ - text_size_; - if (padinfo_.side_ == padding_info::center) + if (padinfo_.side_ == padding_info::right) { - auto reminder = is_left_side ? howmany % 2 : 0; - howmany = (howmany / 2) + reminder; + pad_it(nchars_); } - for (size_t i = 0; i < howmany; i++) + else // padinfo_.side_ == padding_info::center { - dest_.push_back(padinfo_.fill_); + + pad_it( (nchars_/ 2) + (nchars_% 2) ) ; } } - const size_t text_size_; +private: + void pad_it(size_t count) + { + //count = std::min(count, spaces_.size()); + fmt_helper::append_string_view(string_view_t(spaces_.data(), count), dest_); + } + + const padding_info &padinfo_; fmt::memory_buffer &dest_; + size_t nchars_; + string_view_t spaces_ = " " + " "; }; class flag_formatter @@ -664,7 +681,7 @@ public: { const size_t field_size = 6; scoped_pad p(field_size, padinfo_, dest); - fmt_helper::pad6(details::os::pid(), dest); + fmt_helper::pad6(static_cast(details::os::pid()), dest); } }; @@ -1065,7 +1082,7 @@ private: details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end) { using details::padding_info; - const size_t max_width = 4096; + using details::scoped_pad; if (it == end) { @@ -1099,7 +1116,7 @@ private: auto digit = static_cast(*it - '0'); width = width * 10 + digit; } - return details::padding_info{std::min(width, max_width), side}; + return details::padding_info{std::min(width, scoped_pad::max_width), side}; } void compile_pattern_(const std::string &pattern) From a446f187c19efc22d4d275ae397cdfc62c60ad1e Mon Sep 17 00:00:00 2001 From: Pablo Arias Date: Sat, 10 Nov 2018 17:38:23 +0100 Subject: [PATCH 44/65] Fixed deadlock by recursive mutex --- include/spdlog/details/registry.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index e22b8bbc..af261ce7 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -62,7 +62,8 @@ public: if (automatic_registration_) { - register_logger(new_logger); + throw_if_exists_(new_logger->name()); + loggers_[new_logger->name()] = std::move(new_logger); } } From 3cdf2b7f04b0c5b2ecd611880aeae15b098e6821 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 00:31:14 +0200 Subject: [PATCH 45/65] micro optimize scoped_padder --- include/spdlog/details/pattern_formatter.h | 36 ++++++++-------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index f28eb3cd..3c90732d 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -48,31 +48,29 @@ struct padding_info class scoped_pad { public: - - static const size_t max_width = 128; - scoped_pad(size_t wrapped_size, padding_info &padinfo, fmt::memory_buffer &dest): padinfo_(padinfo) , dest_(dest) - , nchars_(padinfo_.width_ > wrapped_size ? padinfo_.width_ - wrapped_size : 0) { - if(nchars_ == 0) + if(padinfo_.width_ <= wrapped_size) { + nchars_ = 0; return; } + nchars_= padinfo.width_ - wrapped_size; if (padinfo_.side_ == padding_info::left) { pad_it(nchars_); nchars_ = 0; - return; } else if(padinfo_.side_ == padding_info::center) { - - pad_it(nchars_/ 2); - return; + auto half_chars = nchars_/ 2; + auto reminder = nchars_ % 2; + pad_it(half_chars); + nchars_= half_chars + reminder; //for the right side } } @@ -83,27 +81,17 @@ public: ~scoped_pad() { - - if(nchars_ == 0) - { - return; - } - - if (padinfo_.side_ == padding_info::right) + if(nchars_) { pad_it(nchars_); } - else // padinfo_.side_ == padding_info::center - { - - pad_it( (nchars_/ 2) + (nchars_% 2) ) ; - } } private: void pad_it(size_t count) { //count = std::min(count, spaces_.size()); + assert(count <= spaces_.size()); fmt_helper::append_string_view(string_view_t(spaces_.data(), count), dest_); } @@ -112,7 +100,7 @@ private: fmt::memory_buffer &dest_; size_t nchars_; string_view_t spaces_ = " " - " "; + " "; }; class flag_formatter @@ -1083,7 +1071,7 @@ private: { using details::padding_info; using details::scoped_pad; - + const size_t max_width = 128; if (it == end) { return padding_info(); @@ -1116,7 +1104,7 @@ private: auto digit = static_cast(*it - '0'); width = width * 10 + digit; } - return details::padding_info{std::min(width, scoped_pad::max_width), side}; + return details::padding_info{std::min(width, max_width), side}; } void compile_pattern_(const std::string &pattern) From ba4ed0eb7fdfbbc28112abd8a40737a03ec13efb Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 00:48:25 +0200 Subject: [PATCH 46/65] micro optimize scoped_padder --- include/spdlog/details/pattern_formatter.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 3c90732d..b76bd485 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -55,22 +55,22 @@ public: if(padinfo_.width_ <= wrapped_size) { - nchars_ = 0; + total_pad_ = 0; return; } - nchars_= padinfo.width_ - wrapped_size; + total_pad_= padinfo.width_ - wrapped_size; if (padinfo_.side_ == padding_info::left) { - pad_it(nchars_); - nchars_ = 0; + pad_it(total_pad_); + total_pad_ = 0; } else if(padinfo_.side_ == padding_info::center) { - auto half_chars = nchars_/ 2; - auto reminder = nchars_ % 2; - pad_it(half_chars); - nchars_= half_chars + reminder; //for the right side + auto half_pad = total_pad_/ 2; + auto reminder = total_pad_ & 1; + pad_it(half_pad); + total_pad_= half_pad + reminder; // for the right side } } @@ -81,9 +81,9 @@ public: ~scoped_pad() { - if(nchars_) + if(total_pad_) { - pad_it(nchars_); + pad_it(total_pad_); } } @@ -98,7 +98,7 @@ private: const padding_info &padinfo_; fmt::memory_buffer &dest_; - size_t nchars_; + size_t total_pad_; string_view_t spaces_ = " " " "; }; From 2ba4b23b855ef9ad661f6889332024ae4e93c12f Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 00:52:21 +0200 Subject: [PATCH 47/65] added padder bench --- bench/Makefile | 8 +++-- bench/padder_bench.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++ example/example.cpp | 29 +++++++++++++++-- 3 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 bench/padder_bench.cpp diff --git a/bench/Makefile b/bench/Makefile index 0cec95e4..11a1037b 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -1,9 +1,9 @@ CXX ?= g++ CXXFLAGS = -march=native -Wall -Wextra -pedantic -Wconversion -std=c++11 -pthread -I../include -fmax-errors=1 -CXX_RELEASE_FLAGS = -Ofast -flto -Wl,--no-as-needed +CXX_RELEASE_FLAGS = -O3 -flto -Wl,--no-as-needed -binaries=bench latency async_bench +binaries=padder_bench all: $(binaries) @@ -17,6 +17,10 @@ async_bench: async_bench.cpp latency: latency.cpp $(CXX) latency.cpp -o latency $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark + + +padder_bench: padder_bench.cpp + $(CXX) padder_bench.cpp -o padder_bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark .PHONY: clean diff --git a/bench/padder_bench.cpp b/bench/padder_bench.cpp new file mode 100644 index 00000000..f9a21d6c --- /dev/null +++ b/bench/padder_bench.cpp @@ -0,0 +1,72 @@ +// +// Copyright(c) 2018 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +// +// latency.cpp : spdlog latency benchmarks +// + +#include "benchmark/benchmark.h" + +#include "spdlog/spdlog.h" +#include "spdlog/details/pattern_formatter.h" + + + +void bench_scoped_pad(benchmark::State &state, size_t wrapped_size, spdlog::details::padding_info padinfo) +{ + fmt::memory_buffer dest; + for (auto _ : state) + { + { + spdlog::details::scoped_pad p(wrapped_size, padinfo, dest); + benchmark::DoNotOptimize(p); + } +// if(dest.size() != (padinfo.width_-wrapped_size)) +// { +// printf("NOT GOOD wrapped_size=%zu\t padinfo.width= %zu\tdest = %zu\n", wrapped_size, padinfo.width_, dest.size()); +// } + dest.clear(); + + } +} + +int main(int argc, char *argv[]) { + + using spdlog::details::padding_info; + spdlog::set_pattern("[tid %t] %v"); + + + std::vector sizes = {0, 2, 4, 8, 16, 32, 64, 128}; + + for (auto size:sizes) + { + size_t wrapped_size = 8; + size_t padding_size = wrapped_size + size; + + std::string title = "scoped_pad::left::" + std::to_string(size); + + benchmark::RegisterBenchmark(title.c_str(), + bench_scoped_pad, + wrapped_size, + padding_info(padding_size, padding_info::left)); + + title = "scoped_pad::right::" + std::to_string(size); + benchmark::RegisterBenchmark(title.c_str(), + bench_scoped_pad, + wrapped_size, + padding_info(padding_size, padding_info::right)); + + title = "scoped_pad::center::" + std::to_string(size); + benchmark::RegisterBenchmark(title.c_str(), + bench_scoped_pad, + wrapped_size, + padding_info(padding_size, padding_info::center)); + } + + + + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); +} diff --git a/example/example.cpp b/example/example.cpp index 1eea343e..55d999d0 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -28,9 +28,32 @@ void clone_example(); int main(int, char *[]) { - spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH); - spdlog::warn("Easy padding in numbers like {:08d}", 12); - spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); + + spdlog::set_pattern("[%-8v]"); + spdlog::info("LEFT"); + spdlog::info("123"); + spdlog::info("1234"); + spdlog::info("12345678"); + spdlog::info("123456789"); + + + spdlog::set_pattern("[%=8v]"); + spdlog::info(""); + spdlog::info("CENTER"); + spdlog::info("123"); + spdlog::info("1234"); + spdlog::info("12345678"); + spdlog::info("123456789"); + + spdlog::set_pattern("[%8v]"); + spdlog::info(""); + spdlog::info("RIGHT"); + spdlog::info("123"); + spdlog::info("1234"); + spdlog::info("12345678"); + spdlog::info("123456789"); + + return 0; spdlog::info("Support for floats {:03.2f}", 1.23456); spdlog::info("Positional args are {1} {0}..", "too", "supported"); spdlog::info("{:>8} aligned, {:>8} aligned", "right", "left"); From e933c5f4816cb88e13e1595324c03b53cc218e30 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:11:09 +0200 Subject: [PATCH 48/65] Fixed example --- example/example.cpp | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/example/example.cpp b/example/example.cpp index 55d999d0..1eea343e 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -28,32 +28,9 @@ void clone_example(); int main(int, char *[]) { - - spdlog::set_pattern("[%-8v]"); - spdlog::info("LEFT"); - spdlog::info("123"); - spdlog::info("1234"); - spdlog::info("12345678"); - spdlog::info("123456789"); - - - spdlog::set_pattern("[%=8v]"); - spdlog::info(""); - spdlog::info("CENTER"); - spdlog::info("123"); - spdlog::info("1234"); - spdlog::info("12345678"); - spdlog::info("123456789"); - - spdlog::set_pattern("[%8v]"); - spdlog::info(""); - spdlog::info("RIGHT"); - spdlog::info("123"); - spdlog::info("1234"); - spdlog::info("12345678"); - spdlog::info("123456789"); - - return 0; + spdlog::info("Welcome to spdlog version {}.{}.{} !", SPDLOG_VER_MAJOR, SPDLOG_VER_MINOR, SPDLOG_VER_PATCH); + spdlog::warn("Easy padding in numbers like {:08d}", 12); + spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42); spdlog::info("Support for floats {:03.2f}", 1.23456); spdlog::info("Positional args are {1} {0}..", "too", "supported"); spdlog::info("{:>8} aligned, {:>8} aligned", "right", "left"); From 7d7ccac4163882786546d5a216d6fae4ca20eb1e Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:17:14 +0200 Subject: [PATCH 49/65] Updated bench cmake --- bench/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bench/CMakeLists.txt b/bench/CMakeLists.txt index 9c9a4365..1a3856ac 100644 --- a/bench/CMakeLists.txt +++ b/bench/CMakeLists.txt @@ -41,4 +41,9 @@ add_executable(latency latency.cpp) set(CMAKE_CXX_STANDARD_LIBRARIES -lbenchmark) target_link_libraries(latency spdlog::spdlog Threads::Threads) + +add_executable(padder_bench padder_bench.cpp) +set(CMAKE_CXX_STANDARD_LIBRARIES -lbenchmark) +target_link_libraries(padder_bench spdlog::spdlog Threads::Threads) + file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs") From dc166cad920d32a07e7db693876add8ba8a2d7ff Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:18:57 +0200 Subject: [PATCH 50/65] Added default pattern support for pattern_formatter to avoid parsing pattern when using default pattern --- include/spdlog/details/pattern_formatter.h | 12 ++++++++++++ include/spdlog/details/registry.h | 2 +- include/spdlog/sinks/sink.h | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index b76bd485..38c28dfc 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -869,6 +869,18 @@ public: compile_pattern_(pattern_); } + // use by default full formatter for if pattern is not given + explicit pattern_formatter( + pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol) + : pattern_() + , eol_(std::move(eol)) + , pattern_time_type_(time_type) + , last_log_secs_(0) + { + std::memset(&cached_tm_, 0, sizeof(cached_tm_)); + formatters_.push_back(details::make_unique(details::padding_info())); + } + pattern_formatter(const pattern_formatter &other) = delete; pattern_formatter &operator=(const pattern_formatter &other) = delete; diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 439395f7..1f15b05e 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -231,7 +231,7 @@ public: private: registry() - : formatter_(new pattern_formatter("%+")) + : formatter_(new pattern_formatter()) { #ifndef SPDLOG_DISABLE_DEFAULT_LOGGER diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index 9f84c378..2f1adc10 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -16,7 +16,7 @@ class sink public: sink() : level_(level::trace) - , formatter_(new pattern_formatter("%+")) + , formatter_(new pattern_formatter()) { } From a6fbb3ef4c99ce750271c066d916ed61b3eadf40 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:25:17 +0200 Subject: [PATCH 51/65] Minor fix to test --- tests/test_registry.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_registry.cpp b/tests/test_registry.cpp index 57976083..d306dba2 100644 --- a/tests/test_registry.cpp +++ b/tests/test_registry.cpp @@ -109,4 +109,5 @@ TEST_CASE("disable automatic registration", "[registry]") // but make sure they are still initialized according to global defaults REQUIRE(logger1->level() == log_level); REQUIRE(logger2->level() == log_level); + spdlog::set_level(spdlog::level::info); } From d99179f822c53c91d7b32b8f99c6dd87e36ea13a Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:26:22 +0200 Subject: [PATCH 52/65] Small refactoring to registry class --- include/spdlog/details/registry.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index b5df6860..bc4565f5 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -42,9 +42,7 @@ public: void register_logger(std::shared_ptr new_logger) { std::lock_guard lock(logger_map_mutex_); - auto logger_name = new_logger->name(); - throw_if_exists_(logger_name); - loggers_[logger_name] = std::move(new_logger); + register_logger_(std::move(new_logger)); } void initialize_logger(std::shared_ptr new_logger) @@ -62,8 +60,7 @@ public: if (automatic_registration_) { - throw_if_exists_(new_logger->name()); - loggers_[new_logger->name()] = std::move(new_logger); + register_logger_(std::move(new_logger)); } } @@ -264,6 +261,13 @@ private: } } + void register_logger_(std::shared_ptr new_logger) + { + auto logger_name = new_logger->name(); + throw_if_exists_(logger_name); + loggers_[logger_name] = std::move(new_logger); + } + std::mutex logger_map_mutex_, flusher_mutex_; std::recursive_mutex tp_mutex_; std::unordered_map> loggers_; From d54e302a28b2482a0dd3119af81b394085372e27 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:26:57 +0200 Subject: [PATCH 53/65] clang-format --- bench/padder_bench.cpp | 34 +++++++--------------- include/spdlog/details/pattern_formatter.h | 30 +++++++++---------- 2 files changed, 24 insertions(+), 40 deletions(-) diff --git a/bench/padder_bench.cpp b/bench/padder_bench.cpp index f9a21d6c..94282abc 100644 --- a/bench/padder_bench.cpp +++ b/bench/padder_bench.cpp @@ -12,8 +12,6 @@ #include "spdlog/spdlog.h" #include "spdlog/details/pattern_formatter.h" - - void bench_scoped_pad(benchmark::State &state, size_t wrapped_size, spdlog::details::padding_info padinfo) { fmt::memory_buffer dest; @@ -23,50 +21,38 @@ void bench_scoped_pad(benchmark::State &state, size_t wrapped_size, spdlog::deta spdlog::details::scoped_pad p(wrapped_size, padinfo, dest); benchmark::DoNotOptimize(p); } -// if(dest.size() != (padinfo.width_-wrapped_size)) -// { -// printf("NOT GOOD wrapped_size=%zu\t padinfo.width= %zu\tdest = %zu\n", wrapped_size, padinfo.width_, dest.size()); -// } + // if(dest.size() != (padinfo.width_-wrapped_size)) + // { + // printf("NOT GOOD wrapped_size=%zu\t padinfo.width= %zu\tdest = %zu\n", wrapped_size, padinfo.width_, dest.size()); + // } dest.clear(); - } } -int main(int argc, char *argv[]) { +int main(int argc, char *argv[]) +{ using spdlog::details::padding_info; spdlog::set_pattern("[tid %t] %v"); - std::vector sizes = {0, 2, 4, 8, 16, 32, 64, 128}; - for (auto size:sizes) + for (auto size : sizes) { size_t wrapped_size = 8; size_t padding_size = wrapped_size + size; std::string title = "scoped_pad::left::" + std::to_string(size); - benchmark::RegisterBenchmark(title.c_str(), - bench_scoped_pad, - wrapped_size, - padding_info(padding_size, padding_info::left)); + benchmark::RegisterBenchmark(title.c_str(), bench_scoped_pad, wrapped_size, padding_info(padding_size, padding_info::left)); title = "scoped_pad::right::" + std::to_string(size); - benchmark::RegisterBenchmark(title.c_str(), - bench_scoped_pad, - wrapped_size, - padding_info(padding_size, padding_info::right)); + benchmark::RegisterBenchmark(title.c_str(), bench_scoped_pad, wrapped_size, padding_info(padding_size, padding_info::right)); title = "scoped_pad::center::" + std::to_string(size); - benchmark::RegisterBenchmark(title.c_str(), - bench_scoped_pad, - wrapped_size, - padding_info(padding_size, padding_info::center)); + benchmark::RegisterBenchmark(title.c_str(), bench_scoped_pad, wrapped_size, padding_info(padding_size, padding_info::center)); } - - benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); } diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 38c28dfc..b9e5d815 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -48,29 +48,29 @@ struct padding_info class scoped_pad { public: - scoped_pad(size_t wrapped_size, padding_info &padinfo, fmt::memory_buffer &dest): - padinfo_(padinfo) + scoped_pad(size_t wrapped_size, padding_info &padinfo, fmt::memory_buffer &dest) + : padinfo_(padinfo) , dest_(dest) { - if(padinfo_.width_ <= wrapped_size) + if (padinfo_.width_ <= wrapped_size) { total_pad_ = 0; return; } - total_pad_= padinfo.width_ - wrapped_size; + total_pad_ = padinfo.width_ - wrapped_size; if (padinfo_.side_ == padding_info::left) { pad_it(total_pad_); total_pad_ = 0; } - else if(padinfo_.side_ == padding_info::center) + else if (padinfo_.side_ == padding_info::center) { - auto half_pad = total_pad_/ 2; + auto half_pad = total_pad_ / 2; auto reminder = total_pad_ & 1; pad_it(half_pad); - total_pad_= half_pad + reminder; // for the right side + total_pad_ = half_pad + reminder; // for the right side } } @@ -81,7 +81,7 @@ public: ~scoped_pad() { - if(total_pad_) + if (total_pad_) { pad_it(total_pad_); } @@ -90,12 +90,11 @@ public: private: void pad_it(size_t count) { - //count = std::min(count, spaces_.size()); + // count = std::min(count, spaces_.size()); assert(count <= spaces_.size()); fmt_helper::append_string_view(string_view_t(spaces_.data(), count), dest_); } - const padding_info &padinfo_; fmt::memory_buffer &dest_; size_t total_pad_; @@ -870,12 +869,11 @@ public: } // use by default full formatter for if pattern is not given - explicit pattern_formatter( - pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol) - : pattern_() - , eol_(std::move(eol)) - , pattern_time_type_(time_type) - , last_log_secs_(0) + explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol) + : pattern_() + , eol_(std::move(eol)) + , pattern_time_type_(time_type) + , last_log_secs_(0) { std::memset(&cached_tm_, 0, sizeof(cached_tm_)); formatters_.push_back(details::make_unique(details::padding_info())); From 6fedffe6d646ddad0d48def251a81de49e6643d1 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:33:08 +0200 Subject: [PATCH 54/65] Moved the SPDLOG_CATCH_AND_HANDLE to logger_impl.h --- include/spdlog/common.h | 10 ---------- include/spdlog/details/logger_impl.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/spdlog/common.h b/include/spdlog/common.h index 51c5195c..3bd30879 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -166,16 +166,6 @@ using filename_t = std::wstring; using filename_t = std::string; #endif -#define SPDLOG_CATCH_AND_HANDLE \ - catch (const std::exception &ex) \ - { \ - err_handler_(ex.what()); \ - } \ - catch (...) \ - { \ - err_handler_("Unknown exeption in logger"); \ - } - namespace details { // make_unique support for pre c++14 diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 850f8639..eb5fcdef 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -10,6 +10,16 @@ #include #include +#define SPDLOG_CATCH_AND_HANDLE \ + catch (const std::exception &ex) \ + { \ + err_handler_(ex.what()); \ + } \ + catch (...) \ + { \ + err_handler_("Unknown exeption in logger"); \ + } + // create logger with given name, sinks and the default pattern formatter // all other ctors will call this one template From 18f0e4ba1afb2101f5c5332c3dfd4c1766e4dc2c Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:43:40 +0200 Subject: [PATCH 55/65] Added some pattern-formatter padding tests --- tests/test_pattern_formatter.cpp | 71 ++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index 7b062a5d..6a99c510 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -129,3 +129,74 @@ TEST_CASE("color range test6", "[pattern_formatter]") REQUIRE(msg.color_range_start == 0); REQUIRE(msg.color_range_end == 2); } + +// +// Test padding +// + +TEST_CASE("level_left_padded", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info] Some message\n"); +} + +TEST_CASE("level_right_padded", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%-8l] %v", spdlog::pattern_time_type::local, "\n") == "[info ] Some message\n"); +} + +TEST_CASE("level_center_padded", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%=8l] %v", spdlog::pattern_time_type::local, "\n") == "[ info ] Some message\n"); +} + +TEST_CASE("short level_left_padded", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I] Some message\n"); +} + +TEST_CASE("short level_right_padded", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%-3L] %v", spdlog::pattern_time_type::local, "\n") == "[I ] Some message\n"); +} + +TEST_CASE("short level_center_padded", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%=3L] %v", spdlog::pattern_time_type::local, "\n") == "[ I ] Some message\n"); +} + +TEST_CASE("left_padded_short", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); +} + +TEST_CASE("right_padded_short", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%-3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); +} + +TEST_CASE("center_padded_short", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%=3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); +} + +TEST_CASE("left_padded_huge", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%-300n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester ]" + " Some message\n"); +} + +TEST_CASE("left_padded_max", "[pattern_formatter]") +{ + REQUIRE(log_to_str("Some message", "[%-128n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester ]" + " Some message\n"); +} +// +//TEST_CASE("right_padded_huge", "[pattern_formatter]") +//{ +// REQUIRE(log_to_str("Some message", "[%-3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); +//} +// +//TEST_CASE("center_padded_huge", "[pattern_formatter]") +//{ +// REQUIRE(log_to_str("Some message", "[%=3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); +//} From 617fcc92cff87a56ee18a28132ee319354fa2e1e Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:48:50 +0200 Subject: [PATCH 56/65] clang-format --- bench/padder_bench.cpp | 7 ------- tests/test_pattern_formatter.cpp | 22 ++++++++-------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/bench/padder_bench.cpp b/bench/padder_bench.cpp index 94282abc..cbb0e67f 100644 --- a/bench/padder_bench.cpp +++ b/bench/padder_bench.cpp @@ -3,10 +3,6 @@ // Distributed under the MIT License (http://opensource.org/licenses/MIT) // -// -// latency.cpp : spdlog latency benchmarks -// - #include "benchmark/benchmark.h" #include "spdlog/spdlog.h" @@ -31,10 +27,7 @@ void bench_scoped_pad(benchmark::State &state, size_t wrapped_size, spdlog::deta int main(int argc, char *argv[]) { - using spdlog::details::padding_info; - spdlog::set_pattern("[tid %t] %v"); - std::vector sizes = {0, 2, 4, 8, 16, 32, 64, 128}; for (auto size : sizes) diff --git a/tests/test_pattern_formatter.cpp b/tests/test_pattern_formatter.cpp index 6a99c510..a098ab26 100644 --- a/tests/test_pattern_formatter.cpp +++ b/tests/test_pattern_formatter.cpp @@ -181,22 +181,16 @@ TEST_CASE("center_padded_short", "[pattern_formatter]") TEST_CASE("left_padded_huge", "[pattern_formatter]") { - REQUIRE(log_to_str("Some message", "[%-300n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester ]" - " Some message\n"); + REQUIRE( + log_to_str("Some message", "[%-300n] %v", spdlog::pattern_time_type::local, "\n") == + "[pattern_tester ]" + " Some message\n"); } TEST_CASE("left_padded_max", "[pattern_formatter]") { - REQUIRE(log_to_str("Some message", "[%-128n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester ]" - " Some message\n"); + REQUIRE( + log_to_str("Some message", "[%-128n] %v", spdlog::pattern_time_type::local, "\n") == + "[pattern_tester ]" + " Some message\n"); } -// -//TEST_CASE("right_padded_huge", "[pattern_formatter]") -//{ -// REQUIRE(log_to_str("Some message", "[%-3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); -//} -// -//TEST_CASE("center_padded_huge", "[pattern_formatter]") -//{ -// REQUIRE(log_to_str("Some message", "[%=3n] %v", spdlog::pattern_time_type::local, "\n") == "[pattern_tester] Some message\n"); -//} From 7b6849578b6c5fd04cbd07e19d9822ce12ded191 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 01:53:51 +0200 Subject: [PATCH 57/65] Fixed some clang-tidy warnings --- include/spdlog/details/pattern_formatter.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index b9e5d815..9de1a6cc 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -876,7 +876,7 @@ public: , last_log_secs_(0) { std::memset(&cached_tm_, 0, sizeof(cached_tm_)); - formatters_.push_back(details::make_unique(details::padding_info())); + formatters_.push_back(details::make_unique(details::padding_info{})); } pattern_formatter(const pattern_formatter &other) = delete; @@ -1084,7 +1084,7 @@ private: const size_t max_width = 128; if (it == end) { - return padding_info(); + return padding_info{}; } padding_info::pad_side side; @@ -1105,10 +1105,10 @@ private: if (it == end || !std::isdigit(static_cast(*it))) { - return padding_info(0, side); + return padding_info{0, side}; } - size_t width = static_cast(*it - '0'); + auto width = static_cast(*it - '0'); for (++it; it != end && std::isdigit(static_cast(*it)); ++it) { auto digit = static_cast(*it - '0'); From f1e79bde2e6a1a0f6b65af19c407d5257371f54c Mon Sep 17 00:00:00 2001 From: Gabi Melman Date: Sun, 11 Nov 2018 02:27:03 +0200 Subject: [PATCH 58/65] Update pattern_formatter.h --- include/spdlog/details/pattern_formatter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 9de1a6cc..672cae25 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -98,8 +98,8 @@ private: const padding_info &padinfo_; fmt::memory_buffer &dest_; size_t total_pad_; - string_view_t spaces_ = " " - " "; + string_view_t spaces_ {" " + " ", 128}; }; class flag_formatter From 0e77c3391bd511b1458bd65aad02fae3e9327556 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 18:15:24 +0200 Subject: [PATCH 59/65] New compile time API using SPDLOG_ACTIVE_LEVEL --- include/spdlog/common.h | 26 ++++++--- include/spdlog/details/logger_impl.h | 8 +-- include/spdlog/details/pattern_formatter.h | 5 +- include/spdlog/logger.h | 12 ++-- include/spdlog/spdlog.h | 64 ++++++++++++++-------- include/spdlog/tweakme.h | 7 +++ tests/includes.h | 3 +- tests/test_macros.cpp | 28 ++++------ 8 files changed, 89 insertions(+), 64 deletions(-) diff --git a/include/spdlog/common.h b/include/spdlog/common.h index 3bd30879..0ce54a9b 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -69,17 +69,29 @@ using level_t = details::null_atomic_int; using level_t = std::atomic; #endif +#define SPDLOG_LEVEL_TRACE 0 +#define SPDLOG_LEVEL_DEBUG 1 +#define SPDLOG_LEVEL_INFO 2 +#define SPDLOG_LEVEL_WARN 3 +#define SPDLOG_LEVEL_ERROR 4 +#define SPDLOG_LEVEL_CRITICAL 5 +#define SPDLOG_LEVEL_OFF 6 + +#if !defined(SPDLOG_ACTIVE_LEVEL) +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +#endif + // Log level enum namespace level { enum level_enum { - trace = 0, - debug = 1, - info = 2, - warn = 3, - err = 4, - critical = 5, - off = 6 + trace = SPDLOG_LEVEL_TRACE, + debug = SPDLOG_LEVEL_DEBUG, + info = SPDLOG_LEVEL_INFO, + warn = SPDLOG_LEVEL_WARN, + err = SPDLOG_LEVEL_ERROR, + critical = SPDLOG_LEVEL_CRITICAL, + off = SPDLOG_LEVEL_OFF, }; #if !defined(SPDLOG_LEVEL_NAMES) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index eb5fcdef..6338586c 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -17,7 +17,7 @@ } \ catch (...) \ { \ - err_handler_("Unknown exeption in logger"); \ + err_handler_("Unknown exception in logger"); \ } // create logger with given name, sinks and the default pattern formatter @@ -26,13 +26,7 @@ template inline spdlog::logger::logger(std::string logger_name, It begin, It end) : name_(std::move(logger_name)) , sinks_(begin, end) - , level_(level::info) - , flush_level_(level::off) - , last_err_time_(0) - , msg_counter_(1) // message counter will start from 1. 0-message id will be - // reserved for control messages { - err_handler_ = [this](const std::string &msg) { this->default_err_handler_(msg); }; } // ctor with sinks as init list diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 672cae25..5e907e92 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -98,8 +98,9 @@ private: const padding_info &padinfo_; fmt::memory_buffer &dest_; size_t total_pad_; - string_view_t spaces_ {" " - " ", 128}; + string_view_t spaces_{" " + " ", + 128}; }; class flag_formatter diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 4e08076b..748529cb 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -158,13 +158,15 @@ protected: // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) void incr_msg_counter_(details::log_msg &msg); + // const spdlog::level_t default_level_{static_cast(SPDLOG_ACTIVE_LEVEL)}; const std::string name_; + std::vector sinks_; - spdlog::level_t level_; - spdlog::level_t flush_level_; - log_err_handler err_handler_; - std::atomic last_err_time_; - std::atomic msg_counter_; + spdlog::level_t level_{static_cast(SPDLOG_ACTIVE_LEVEL)}; + spdlog::level_t flush_level_{level::off}; + log_err_handler err_handler_{[this](const std::string &msg) { this->default_err_handler_(msg); }}; + std::atomic last_err_time_{0}; + std::atomic msg_counter_{1}; }; } // namespace spdlog diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 8c07012e..1f3e26ba 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -290,36 +290,54 @@ inline void critical(const wchar_t *fmt, const Args &... args) #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT -// -// Trace & Debug can be switched on/off at compile time with zero cost. -// Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in tweakme.h to enable. -// SPDLOG_TRACE(..) will also print current file and line. -// -// Example: -// spdlog::set_level(spdlog::level::trace); -// SPDLOG_TRACE(my_logger, "another trace message {} {}", 1, 2); -// +// compile time level. defaults to info + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE +#define SPDLOG_LOGGER_TRACE(logger, ...) logger->trace(__VA_ARGS__) +#define SPDLOG_TRACE(...) spdlog::trace(__VA_ARGS__) +#else +#define SPDLOG_LOGGER_TRACE(logger, ...) (void)0 +#define SPDLOG_TRACE(...) (void)0 +#endif -#ifdef SPDLOG_TRACE_ON -#define SPDLOG_STR_H(x) #x -#define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x) -#ifdef _MSC_VER -#define SPDLOG_TRACE(logger, ...) \ - logger->trace("[ "__FILE__ \ - "(" SPDLOG_STR_HELPER(__LINE__) ")] " __VA_ARGS__) +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_DEBUG +#define SPDLOG_LOGGER_DEBUG(logger, ...) logger->debug(__VA_ARGS__) +#define SPDLOG_DEBUG(...) spdlog::debug(__VA_ARGS__) #else -#define SPDLOG_TRACE(logger, ...) \ - logger->trace("[" __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) "]" \ - " " __VA_ARGS__) +#define SPDLOG_LOGGER_DEBUG(logger, ...) (void)0 +#define SPDLOG_DEBUG(...) (void)0 #endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_INFO +#define SPDLOG_LOGGER_INFO(logger, ...) logger->info(__VA_ARGS__) +#define SPDLOG_INFO(...) spdlog::info(__VA_ARGS__) +#else +#define SPDLOG_LOGGER_INFO(logger, ...) (void)0 +#define SPDLOG_INFO(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_WARN +#define SPDLOG_LOGGER_WARN(logger, ...) logger->warn(__VA_ARGS__) +#define SPDLOG_WARN(...) spdlog::warn(__VA_ARGS__) +#else +#define SPDLOG_LOGGER_WARN(logger, ...) (void)0 +#define SPDLOG_WARN(...) (void)0 +#endif + +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_ERROR +#define SPDLOG_LOGGER_ERROR(logger, ...) logger->error(__VA_ARGS__) +#define SPDLOG_ERROR(...) spdlog::error(__VA_ARGS__) #else -#define SPDLOG_TRACE(logger, ...) (void)0 +#define SPDLOG_LOGGER_ERROR(logger, ...) (void)0 +#define SPDLOG_ERROR(...) (void)0 #endif -#ifdef SPDLOG_DEBUG_ON -#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) +#if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_CRITICAL +#define SPDLOG_LOGGER_CRITICAL(logger, ...) logger->critical(__VA_ARGS__) +#define SPDLOG_CRITICAL(...) spdlog::critical(__VA_ARGS__) #else -#define SPDLOG_DEBUG(logger, ...) (void)0 +#define SPDLOG_LOGGER_CRITICAL(logger, ...) (void)0 +#define SPDLOG_CRITICAL(...) (void)0 #endif } // namespace spdlog diff --git a/include/spdlog/tweakme.h b/include/spdlog/tweakme.h index d91159f7..0d77dadc 100644 --- a/include/spdlog/tweakme.h +++ b/include/spdlog/tweakme.h @@ -128,3 +128,10 @@ // // #define SPDLOG_DISABLE_DEFAULT_LOGGER /////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Uncomment and set to compile time level with zero cost (default is INFO). +// Macros like SPDLOG_DEBUG(..), SPDLOG_INFO(..) will expand to empty statements if not enabled +// +// #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO +/////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/tests/includes.h b/tests/includes.h index 3379f2c2..54601602 100644 --- a/tests/includes.h +++ b/tests/includes.h @@ -10,8 +10,7 @@ #include #include -#define SPDLOG_TRACE_ON -#define SPDLOG_DEBUG_ON +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #define SPDLOG_ENABLE_MESSAGE_COUNTER #include "spdlog/spdlog.h" diff --git a/tests/test_macros.cpp b/tests/test_macros.cpp index 0b3e0b7d..cf2bb136 100644 --- a/tests/test_macros.cpp +++ b/tests/test_macros.cpp @@ -4,8 +4,13 @@ #include "includes.h" +#if SPDLOG_ACTIVE_LEVEL != SPDLOG_LEVEL_DEBUG +#error "Invalid SPDLOG_ACTIVE_LEVEL in test. Should be SPDLOG_LEVEL_DEBUG" +#endif + TEST_CASE("debug and trace w/o format string", "[macros]]") { + prepare_logdir(); std::string filename = "logs/simple_log"; @@ -13,28 +18,15 @@ TEST_CASE("debug and trace w/o format string", "[macros]]") logger->set_pattern("%v"); logger->set_level(spdlog::level::trace); - SPDLOG_TRACE(logger, "Test message 1"); - SPDLOG_DEBUG(logger, "Test message 2"); + SPDLOG_LOGGER_TRACE(logger, "Test message 1"); + SPDLOG_LOGGER_DEBUG(logger, "Test message 2"); logger->flush(); REQUIRE(ends_with(file_contents(filename), "Test message 2\n")); - REQUIRE(count_lines(filename) == 2); + REQUIRE(count_lines(filename) == 1); } -TEST_CASE("debug and trace with format strings", "[macros]]") +TEST_CASE("disable param evaluation", "[macros]") { - prepare_logdir(); - std::string filename = "logs/simple_log"; - - auto logger = spdlog::create("logger", filename); - logger->set_pattern("%v"); - logger->set_level(spdlog::level::trace); - - SPDLOG_TRACE(logger, "Test message {}", 1); - // SPDLOG_DEBUG(logger, "Test message 2"); - SPDLOG_DEBUG(logger, "Test message {}", 222); - logger->flush(); - - REQUIRE(ends_with(file_contents(filename), "Test message 222\n")); - REQUIRE(count_lines(filename) == 2); + SPDLOG_TRACE("Test message {}", throw std::runtime_error("Should not be evaluated")); } From 48597a94e8b5edb6fbcdc1013f75647ea3634f02 Mon Sep 17 00:00:00 2001 From: gabime Date: Sun, 11 Nov 2018 18:20:53 +0200 Subject: [PATCH 60/65] Updated example --- example/example.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/example/example.cpp b/example/example.cpp index 1eea343e..b54d0a73 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -22,7 +22,8 @@ void err_handler_example(); void syslog_example(); void clone_example(); -#define SPDLOG_TRACE_ON +// activate compile time macros to be debug or above +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG #include "spdlog/spdlog.h" @@ -160,12 +161,18 @@ void binary_example() } // Compile time log levels. -// Must define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON before including spdlog.h to turn them on. +// define SPDLOG_ACTIVE_LEVEL to required level (e.g. SPDLOG_LEVEL_TRACE) void trace_example() { + + // trace from default logger + SPDLOG_TRACE("Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); + // debug from default logger + SPDLOG_DEBUG("Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); + + // trace from logger object auto logger = spdlog::get("file_logger"); - SPDLOG_TRACE(logger, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 3.23); - SPDLOG_DEBUG(logger, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 1, 3.23); + SPDLOG_LOGGER_TRACE(logger, "another trace message"); } // A logger with multiple sinks (stdout and file) - each with a different format and log level. From 526f21ae7f738e387dbb33c7d69981e7ebebd97b Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 12 Nov 2018 10:39:34 +0200 Subject: [PATCH 61/65] Fixed #902 --- include/spdlog/details/pattern_formatter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 672cae25..c79e4f11 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -1114,7 +1114,7 @@ private: auto digit = static_cast(*it - '0'); width = width * 10 + digit; } - return details::padding_info{std::min(width, max_width), side}; + return details::padding_info{std::min(width, max_width), side}; } void compile_pattern_(const std::string &pattern) From 971c1f46b087ba3944c85b92aad67dc8896ac803 Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 12 Nov 2018 11:07:51 +0200 Subject: [PATCH 62/65] Updated latency tests --- bench/Makefile | 12 ++++++------ bench/latency.cpp | 20 ++++++++++++++++---- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/bench/Makefile b/bench/Makefile index 11a1037b..181f4664 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -1,27 +1,27 @@ CXX ?= g++ -CXXFLAGS = -march=native -Wall -Wextra -pedantic -Wconversion -std=c++11 -pthread -I../include -fmax-errors=1 +CXXFLAGS = -march=native -Wall -Wextra -pedantic -Wconversion -std=c++11 -pthread -I../include -fmax-errors=1 CXX_RELEASE_FLAGS = -O3 -flto -Wl,--no-as-needed -binaries=padder_bench +binaries=bench.cpp async_bench latency padder_bench all: $(binaries) bench: bench.cpp $(CXX) bench.cpp -o bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS) - + async_bench: async_bench.cpp $(CXX) async_bench.cpp -o async_bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS) - - + + latency: latency.cpp $(CXX) latency.cpp -o latency $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark padder_bench: padder_bench.cpp $(CXX) padder_bench.cpp -o padder_bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark - + .PHONY: clean diff --git a/bench/latency.cpp b/bench/latency.cpp index 6df593dd..78ee1786 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -59,6 +59,18 @@ void bench_logger(benchmark::State &state, std::shared_ptr logge } } +void bench_disabled_macro(benchmark::State &state, std::shared_ptr logger) +{ + int i = 0; + benchmark::DoNotOptimize(i); //prevent unused warnings + benchmark::DoNotOptimize(logger); //prevent unused warnings + for (auto _ : state) + { + SPDLOG_LOGGER_DEBUG(logger, "Hello logger: msg number {}...............", i++); + SPDLOG_DEBUG("Hello logger: msg number {}...............", i++); + } +} + int main(int argc, char *argv[]) { @@ -74,14 +86,14 @@ int main(int argc, char *argv[]) prepare_logdir(); - // Single threaded benchmarks + // disabled loggers auto disabled_logger = std::make_shared("bench", std::make_shared()); disabled_logger->set_level(spdlog::level::off); - benchmark::RegisterBenchmark("disabled-level", bench_logger, disabled_logger)->UseRealTime(); + benchmark::RegisterBenchmark("disabled-at-compile-time", bench_disabled_macro, disabled_logger); + benchmark::RegisterBenchmark("disabled-at-runtime", bench_logger, disabled_logger); auto null_logger_st = std::make_shared("bench", std::make_shared()); - benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st))->UseRealTime(); - + benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st)); benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st); // basic_st From c5069135d7c04ba0a5241888f2ec51f236ccd6aa Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 12 Nov 2018 12:01:10 +0200 Subject: [PATCH 63/65] Improved compile time level support --- bench/latency.cpp | 4 ++-- example/example.cpp | 3 --- include/spdlog/details/logger_impl.h | 5 +++++ include/spdlog/details/registry.h | 2 +- include/spdlog/logger.h | 6 +++--- include/spdlog/spdlog.h | 5 ++++- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/bench/latency.cpp b/bench/latency.cpp index 78ee1786..25b99f5c 100644 --- a/bench/latency.cpp +++ b/bench/latency.cpp @@ -62,8 +62,8 @@ void bench_logger(benchmark::State &state, std::shared_ptr logge void bench_disabled_macro(benchmark::State &state, std::shared_ptr logger) { int i = 0; - benchmark::DoNotOptimize(i); //prevent unused warnings - benchmark::DoNotOptimize(logger); //prevent unused warnings + benchmark::DoNotOptimize(i); // prevent unused warnings + benchmark::DoNotOptimize(logger); // prevent unused warnings for (auto _ : state) { SPDLOG_LOGGER_DEBUG(logger, "Hello logger: msg number {}...............", i++); diff --git a/example/example.cpp b/example/example.cpp index b54d0a73..8a103fc3 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -22,9 +22,6 @@ void err_handler_example(); void syslog_example(); void clone_example(); -// activate compile time macros to be debug or above -#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG - #include "spdlog/spdlog.h" int main(int, char *[]) diff --git a/include/spdlog/details/logger_impl.h b/include/spdlog/details/logger_impl.h index 6338586c..efe6a66a 100644 --- a/include/spdlog/details/logger_impl.h +++ b/include/spdlog/details/logger_impl.h @@ -327,6 +327,11 @@ inline bool spdlog::logger::should_flush_(const details::log_msg &msg) return (msg.level >= flush_level) && (msg.level != level::off); } +inline spdlog::level::level_enum spdlog::logger::default_level() +{ + return static_cast(SPDLOG_ACTIVE_LEVEL); +} + inline spdlog::level::level_enum spdlog::logger::level() const { return static_cast(level_.load(std::memory_order_relaxed)); diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index bc4565f5..ccd53955 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -272,7 +272,7 @@ private: std::recursive_mutex tp_mutex_; std::unordered_map> loggers_; std::unique_ptr formatter_; - level::level_enum level_ = level::info; + level::level_enum level_ = spdlog::logger::default_level(); level::level_enum flush_level_ = level::off; log_err_handler err_handler_; std::shared_ptr tp_; diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 748529cb..a1757574 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -121,6 +121,8 @@ public: bool should_log(level::level_enum msg_level) const; void set_level(level::level_enum log_level); + + static level::level_enum default_level(); level::level_enum level() const; const std::string &name() const; @@ -158,11 +160,9 @@ protected: // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) void incr_msg_counter_(details::log_msg &msg); - // const spdlog::level_t default_level_{static_cast(SPDLOG_ACTIVE_LEVEL)}; const std::string name_; - std::vector sinks_; - spdlog::level_t level_{static_cast(SPDLOG_ACTIVE_LEVEL)}; + spdlog::level_t level_{spdlog::logger::default_level()}; spdlog::level_t flush_level_{level::off}; log_err_handler err_handler_{[this](const std::string &msg) { this->default_err_handler_(msg); }}; std::atomic last_err_time_{0}; diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 1f3e26ba..200cbd1d 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -290,7 +290,10 @@ inline void critical(const wchar_t *fmt, const Args &... args) #endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT -// compile time level. defaults to info +// +// compile time macros. +// can be enabled/disabled using SPDLOG_ACTIVE_LEVEL (info by default). +// #if SPDLOG_ACTIVE_LEVEL <= SPDLOG_LEVEL_TRACE #define SPDLOG_LOGGER_TRACE(logger, ...) logger->trace(__VA_ARGS__) From 9b5b4cd505143202fd785af6a077c409327f0683 Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 12 Nov 2018 12:12:33 +0200 Subject: [PATCH 64/65] comment --- include/spdlog/logger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index a1757574..d1da624f 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -153,8 +153,8 @@ protected: bool should_flush_(const details::log_msg &msg); - // default error handler: print the error to stderr with the max rate of 1 - // message/minute + // default error handler. + // print the error to stderr with the max rate of 1 message/minute. void default_err_handler_(const std::string &msg); // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)) From 314991ac6020ba7dadf4d3a3d251e122b382881e Mon Sep 17 00:00:00 2001 From: gabime Date: Mon, 12 Nov 2018 12:46:07 +0200 Subject: [PATCH 65/65] Fixed pattern formatter constructor bug --- include/spdlog/details/pattern_formatter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index a0dcfea4..9d018fb8 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -871,7 +871,7 @@ public: // use by default full formatter for if pattern is not given explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol) - : pattern_() + : pattern_("%+") , eol_(std::move(eol)) , pattern_time_type_(time_type) , last_log_secs_(0)