diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h index 94a1edbd..b0b644a4 100644 --- a/include/spdlog/async_logger.h +++ b/include/spdlog/async_logger.h @@ -19,7 +19,6 @@ // Upon destruction, logs all remaining messages in the queue before // destructing.. - #include "spdlog/logger.h" namespace spdlog { @@ -69,5 +68,3 @@ private: #ifdef SPDLOG_HEADER_ONLY #include "spdlog/impl/async_logger.cpp" #endif // SPDLOG_HEADER_ONLY - - diff --git a/include/spdlog/common.h b/include/spdlog/common.h index a4c3407c..add4000b 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -70,7 +70,6 @@ #define SPDLOG_FUNCTION __FUNCTION__ #endif - namespace spdlog { class formatter; diff --git a/include/spdlog/details/file_helper.h b/include/spdlog/details/file_helper.h index 62cd2ee3..9f7fceaa 100644 --- a/include/spdlog/details/file_helper.h +++ b/include/spdlog/details/file_helper.h @@ -24,17 +24,17 @@ public: file_helper(const file_helper &) = delete; file_helper &operator=(const file_helper &) = delete; - ~file_helper(); + ~file_helper(); - void open(const filename_t &fname, bool truncate = false); - void reopen(bool truncate); - void flush(); - void close(); + void open(const filename_t &fname, bool truncate = false); + void reopen(bool truncate); + void flush(); + void close(); void write(const fmt::memory_buffer &buf); - size_t size() const; + size_t size() const; const filename_t &filename() const; static bool file_exists(const filename_t &fname); - + // // return file path and its extension: // @@ -57,6 +57,6 @@ private: } // namespace details } // namespace spdlog -#ifdef SPDLOG_HEADER_ONLY +#ifdef SPDLOG_HEADER_ONLY #include "spdlog/impl/file_helper.cpp" #endif // ! SPDLOG_HEADER_ONLY diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 3ac381be..e9cacbb7 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -13,7 +13,7 @@ namespace details { struct log_msg { log_msg(source_loc loc, const std::string *loggers_name, level::level_enum lvl, string_view_t view); - + log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_t view); log_msg(const log_msg &other) = default; @@ -33,6 +33,6 @@ struct log_msg } // namespace details } // namespace spdlog -#ifdef SPDLOG_HEADER_ONLY +#ifdef SPDLOG_HEADER_ONLY #include "spdlog/impl/log_msg.cpp" #endif // SPDLOG_HEADER_ONLY diff --git a/include/spdlog/details/pattern_formatter.h b/include/spdlog/details/pattern_formatter.h index 64686017..210efd23 100644 --- a/include/spdlog/details/pattern_formatter.h +++ b/include/spdlog/details/pattern_formatter.h @@ -20,7 +20,6 @@ namespace spdlog { namespace details { - // padding information. struct padding_info { @@ -61,26 +60,22 @@ protected: padding_info padinfo_; }; -} +} // namespace details class pattern_formatter final : public formatter { public: explicit pattern_formatter( - std::string pattern, - pattern_time_type time_type = pattern_time_type::local, - std::string eol = spdlog::details::os::default_eol); - + std::string pattern, pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); + // use default pattern is not given - explicit pattern_formatter( - pattern_time_type time_type = pattern_time_type::local, - std::string eol = spdlog::details::os::default_eol); + explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol); pattern_formatter(const pattern_formatter &other) = delete; pattern_formatter &operator=(const pattern_formatter &other) = delete; std::unique_ptr clone() const override; - void format(const details::log_msg &msg, fmt::memory_buffer &dest) override; + void format(const details::log_msg &msg, fmt::memory_buffer &dest) override; private: std::string pattern_; @@ -89,15 +84,15 @@ private: std::tm cached_tm_; std::chrono::seconds last_log_secs_; std::vector> formatters_; - std::tm get_time_(const details::log_msg &msg); + std::tm get_time_(const details::log_msg &msg); void handle_flag_(char flag, details::padding_info padding); - + // 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); - + void compile_pattern_(const std::string &pattern); }; } // namespace spdlog diff --git a/include/spdlog/details/registry.h b/include/spdlog/details/registry.h index 5afff601..93d35e87 100644 --- a/include/spdlog/details/registry.h +++ b/include/spdlog/details/registry.h @@ -32,59 +32,59 @@ public: registry(const registry &) = delete; registry &operator=(const registry &) = delete; - void register_logger(std::shared_ptr new_logger); - void initialize_logger(std::shared_ptr new_logger); - std::shared_ptr get(const std::string &logger_name); + void register_logger(std::shared_ptr new_logger); + void initialize_logger(std::shared_ptr new_logger); + std::shared_ptr get(const std::string &logger_name); std::shared_ptr default_logger(); - + // Return raw ptr to the default logger. // To be used directly by the spdlog default api (e.g. spdlog::info) // This make the default API faster, but cannot be used concurrently with set_default_logger(). // e.g do not call set_default_logger() from one thread while calling spdlog::info() from another. logger *get_default_raw(); - + // set default logger. // default logger is stored in default_logger_ (for faster retrieval) and in the loggers_ map. void set_default_logger(std::shared_ptr new_default_logger); void set_tp(std::shared_ptr tp); - + std::shared_ptr get_tp(); - + // Set global formatter. Each sink in each logger will get a clone of this object - void set_formatter(std::unique_ptr formatter); + void set_formatter(std::unique_ptr formatter); void set_level(level::level_enum log_level); - + void flush_on(level::level_enum log_level); - + void flush_every(std::chrono::seconds interval); - + void set_error_handler(void (*handler)(const std::string &msg)); - + void apply_all(const std::function)> &fun); - + void flush_all(); - + void drop(const std::string &logger_name); - - void drop_all(); + + void drop_all(); // clean all resources and threads started by the registry - void shutdown(); + void shutdown(); + + std::recursive_mutex &tp_mutex(); - std::recursive_mutex &tp_mutex(); - void set_automatic_registration(bool automatic_regsistration); - - static registry &instance(); + + static registry &instance(); private: - registry(); + registry(); ~registry() = default; - void throw_if_exists_(const std::string &logger_name); - void register_logger_(std::shared_ptr new_logger); + void throw_if_exists_(const std::string &logger_name); + void register_logger_(std::shared_ptr new_logger); std::mutex logger_map_mutex_, flusher_mutex_; std::recursive_mutex tp_mutex_; std::unordered_map> loggers_; diff --git a/include/spdlog/impl/async_logger.cpp b/include/spdlog/impl/async_logger.cpp index 94e8e546..e915042e 100644 --- a/include/spdlog/impl/async_logger.cpp +++ b/include/spdlog/impl/async_logger.cpp @@ -2,7 +2,6 @@ #include "spdlog/async_logger.h" #endif - // async logger implementation // uses a thread pool to perform the actual logging @@ -15,22 +14,22 @@ template SPDLOG_INLINE spdlog::async_logger::async_logger( - std::string logger_name, It begin, It end, std::weak_ptr tp, async_overflow_policy overflow_policy) - : logger(std::move(logger_name), begin, end) - , thread_pool_(std::move(tp)) - , overflow_policy_(overflow_policy) + std::string logger_name, It begin, It end, std::weak_ptr tp, async_overflow_policy overflow_policy) + : logger(std::move(logger_name), begin, end) + , thread_pool_(std::move(tp)) + , overflow_policy_(overflow_policy) { } SPDLOG_INLINE spdlog::async_logger::async_logger( - std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, async_overflow_policy overflow_policy) - : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy) + std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, async_overflow_policy overflow_policy) + : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy) { } SPDLOG_INLINE spdlog::async_logger::async_logger( - std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy) - : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) + std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy) + : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) { } @@ -118,6 +117,3 @@ SPDLOG_INLINE std::shared_ptr spdlog::async_logger::clone(std::s cloned->set_error_handler(this->custom_err_handler_); return std::move(cloned); } - - - diff --git a/include/spdlog/impl/file_helper.cpp b/include/spdlog/impl/file_helper.cpp index 781931b0..70a86eb8 100644 --- a/include/spdlog/impl/file_helper.cpp +++ b/include/spdlog/impl/file_helper.cpp @@ -17,116 +17,115 @@ #include namespace spdlog { -namespace details +namespace details { +SPDLOG_INLINE file_helper::~file_helper() { - SPDLOG_INLINE file_helper::~file_helper() - { - close(); - } + close(); +} - SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) +SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate) +{ + close(); + auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); + _filename = fname; + for (int tries = 0; tries < open_tries; ++tries) { - close(); - auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab"); - _filename = fname; - for (int tries = 0; tries < open_tries; ++tries) + if (!os::fopen_s(&fd_, fname, mode)) { - if (!os::fopen_s(&fd_, fname, mode)) - { - return; - } - - details::os::sleep_for_millis(open_interval); + return; } - throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno); + details::os::sleep_for_millis(open_interval); } - SPDLOG_INLINE void file_helper::reopen(bool truncate) + throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno); +} + +SPDLOG_INLINE void file_helper::reopen(bool truncate) +{ + if (_filename.empty()) { - if (_filename.empty()) - { - throw spdlog_ex("Failed re opening file - was not opened before"); - } - open(_filename, truncate); + throw spdlog_ex("Failed re opening file - was not opened before"); } + open(_filename, truncate); +} - SPDLOG_INLINE void file_helper::flush() +SPDLOG_INLINE void file_helper::flush() +{ + std::fflush(fd_); +} + +SPDLOG_INLINE void file_helper::close() +{ + if (fd_ != nullptr) { - std::fflush(fd_); + std::fclose(fd_); + fd_ = nullptr; } +} - SPDLOG_INLINE void file_helper::close() +SPDLOG_INLINE void file_helper::write(const fmt::memory_buffer &buf) +{ + size_t msg_size = buf.size(); + auto data = buf.data(); + if (std::fwrite(data, 1, msg_size, fd_) != msg_size) { - if (fd_ != nullptr) - { - std::fclose(fd_); - fd_ = nullptr; - } + throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno); } +} - SPDLOG_INLINE void file_helper::write(const fmt::memory_buffer &buf) +SPDLOG_INLINE size_t file_helper::size() const +{ + if (fd_ == nullptr) { - size_t msg_size = buf.size(); - auto data = buf.data(); - if (std::fwrite(data, 1, msg_size, fd_) != msg_size) - { - throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno); - } + throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)); } + return os::filesize(fd_); +} - SPDLOG_INLINE size_t file_helper::size() const +SPDLOG_INLINE const filename_t &file_helper::filename() const +{ + return _filename; +} + +SPDLOG_INLINE bool file_helper::file_exists(const filename_t &fname) +{ + return os::file_exists(fname); +} + +// +// return file path and its extension: +// +// "mylog.txt" => ("mylog", ".txt") +// "mylog" => ("mylog", "") +// "mylog." => ("mylog.", "") +// "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") +// +// the starting dot in filenames is ignored (hidden files): +// +// ".mylog" => (".mylog". "") +// "my_folder/.mylog" => ("my_folder/.mylog", "") +// "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") +SPDLOG_INLINE std::tuple file_helper::split_by_extension(const filename_t &fname) +{ + auto ext_index = fname.rfind('.'); + + // no valid extension found - return whole path and empty string as + // extension + if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) { - if (fd_ == nullptr) - { - throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename)); - } - return os::filesize(fd_); + return std::make_tuple(fname, filename_t()); } - SPDLOG_INLINE const filename_t &file_helper::filename() const + // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" + auto folder_index = fname.rfind(details::os::folder_sep); + if (folder_index != filename_t::npos && folder_index >= ext_index - 1) { - return _filename; + return std::make_tuple(fname, filename_t()); } - SPDLOG_INLINE bool file_helper::file_exists(const filename_t &fname) - { - return os::file_exists(fname); - } - - // - // return file path and its extension: - // - // "mylog.txt" => ("mylog", ".txt") - // "mylog" => ("mylog", "") - // "mylog." => ("mylog.", "") - // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt") - // - // the starting dot in filenames is ignored (hidden files): - // - // ".mylog" => (".mylog". "") - // "my_folder/.mylog" => ("my_folder/.mylog", "") - // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt") - SPDLOG_INLINE std::tuple file_helper::split_by_extension(const filename_t &fname) - { - auto ext_index = fname.rfind('.'); - - // no valid extension found - return whole path and empty string as - // extension - if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1) - { - return std::make_tuple(fname, filename_t()); - } - - // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile" - auto folder_index = fname.rfind(details::os::folder_sep); - if (folder_index != filename_t::npos && folder_index >= ext_index - 1) - { - return std::make_tuple(fname, filename_t()); - } - - // finally - return a valid base and extension tuple - return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); - } + // finally - return a valid base and extension tuple + return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index)); +} } // namespace details } // namespace spdlog diff --git a/include/spdlog/impl/log_msg.cpp b/include/spdlog/impl/log_msg.cpp index 241bcf5d..ec4f8642 100644 --- a/include/spdlog/impl/log_msg.cpp +++ b/include/spdlog/impl/log_msg.cpp @@ -1,12 +1,10 @@ #include "spdlog/details/os.h" #include "spdlog/sinks/sink.h" - -#ifndef SPDLOG_HEADER_ONLY -#include "spdlog/details/log_msg.h" -#endif - - - + +#ifndef SPDLOG_HEADER_ONLY +#include "spdlog/details/log_msg.h" +#endif + SPDLOG_INLINE spdlog::details::log_msg::log_msg( spdlog::source_loc loc, const std::string *loggers_name, spdlog::level::level_enum lvl, spdlog::string_view_t view) : logger_name(loggers_name) diff --git a/include/spdlog/impl/logger.cpp b/include/spdlog/impl/logger.cpp index d3200537..7dcfc973 100644 --- a/include/spdlog/impl/logger.cpp +++ b/include/spdlog/impl/logger.cpp @@ -160,11 +160,11 @@ SPDLOG_INLINE bool spdlog::logger::should_flush_(const spdlog::details::log_msg } SPDLOG_INLINE void spdlog::logger::err_handler_(const std::string &msg) -{ - if (custom_err_handler_) - { - custom_err_handler_(msg); - } +{ + if (custom_err_handler_) + { + custom_err_handler_(msg); + } else { auto tm_time = spdlog::details::os::localtime(); diff --git a/include/spdlog/impl/pattern_formatter.cpp b/include/spdlog/impl/pattern_formatter.cpp index 810d8a23..f1d43cf8 100644 --- a/include/spdlog/impl/pattern_formatter.cpp +++ b/include/spdlog/impl/pattern_formatter.cpp @@ -959,308 +959,304 @@ private: } // namespace details +SPDLOG_INLINE pattern_formatter::pattern_formatter(std::string pattern, pattern_time_type time_type, std::string eol) + : pattern_(std::move(pattern)) + , eol_(std::move(eol)) + , pattern_time_type_(time_type) + , last_log_secs_(0) +{ + std::memset(&cached_tm_, 0, sizeof(cached_tm_)); + compile_pattern_(pattern_); +} - SPDLOG_INLINE pattern_formatter::pattern_formatter( - std::string pattern, pattern_time_type time_type, std::string eol) - : pattern_(std::move(pattern)) - , eol_(std::move(eol)) - , pattern_time_type_(time_type) - , last_log_secs_(0) - { - std::memset(&cached_tm_, 0, sizeof(cached_tm_)); - compile_pattern_(pattern_); - } +// use by default full formatter for if pattern is not given +SPDLOG_INLINE pattern_formatter::pattern_formatter(pattern_time_type time_type, std::string 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{})); +} - // use by default full formatter for if pattern is not given - SPDLOG_INLINE pattern_formatter::pattern_formatter(pattern_time_type time_type, std::string 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{})); - } +SPDLOG_INLINE std::unique_ptr pattern_formatter::clone() const +{ + return details::make_unique(pattern_, pattern_time_type_, eol_); +} - - SPDLOG_INLINE std::unique_ptr pattern_formatter::clone() const - { - return details::make_unique(pattern_, pattern_time_type_, eol_); - } - - SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, fmt::memory_buffer &dest) - { +SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, fmt::memory_buffer &dest) +{ #ifndef SPDLOG_NO_DATETIME - auto secs = std::chrono::duration_cast(msg.time.time_since_epoch()); - if (secs != last_log_secs_) - { - cached_tm_ = get_time_(msg); - last_log_secs_ = secs; - } + auto secs = std::chrono::duration_cast(msg.time.time_since_epoch()); + if (secs != last_log_secs_) + { + cached_tm_ = get_time_(msg); + last_log_secs_ = secs; + } #endif - for (auto &f : formatters_) - { - f->format(msg, cached_tm_, dest); - } - // write eol - details::fmt_helper::append_string_view(eol_, dest); + for (auto &f : formatters_) + { + f->format(msg, cached_tm_, dest); + } + // write eol + details::fmt_helper::append_string_view(eol_, dest); +} + +SPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg) +{ + if (pattern_time_type_ == pattern_time_type::local) + { + return details::os::localtime(log_clock::to_time_t(msg.time)); + } + return details::os::gmtime(log_clock::to_time_t(msg.time)); +} + +SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_info padding) +{ + switch (flag) + { + + case ('+'): // default formatter + formatters_.push_back(details::make_unique(padding)); + break; + + case 'n': // logger name + formatters_.push_back(details::make_unique(padding)); + break; + + case 'l': // level + formatters_.push_back(details::make_unique(padding)); + break; + + case 'L': // short level + formatters_.push_back(details::make_unique(padding)); + break; + + case ('t'): // thread id + formatters_.push_back(details::make_unique(padding)); + break; + + case ('v'): // the message text + formatters_.push_back(details::make_unique(padding)); + break; + + case ('a'): // weekday + formatters_.push_back(details::make_unique(padding)); + break; + + case ('A'): // short weekday + formatters_.push_back(details::make_unique(padding)); + break; + + case ('b'): + case ('h'): // month + formatters_.push_back(details::make_unique(padding)); + break; + + case ('B'): // short month + formatters_.push_back(details::make_unique(padding)); + break; + + case ('c'): // datetime + formatters_.push_back(details::make_unique(padding)); + break; + + case ('C'): // year 2 digits + formatters_.push_back(details::make_unique(padding)); + break; + + case ('Y'): // year 4 digits + formatters_.push_back(details::make_unique(padding)); + break; + + case ('D'): + case ('x'): // datetime MM/DD/YY + formatters_.push_back(details::make_unique(padding)); + break; + + case ('m'): // month 1-12 + formatters_.push_back(details::make_unique(padding)); + break; + + case ('d'): // day of month 1-31 + formatters_.push_back(details::make_unique(padding)); + break; + + case ('H'): // hours 24 + formatters_.push_back(details::make_unique(padding)); + break; + + case ('I'): // hours 12 + formatters_.push_back(details::make_unique(padding)); + break; + + case ('M'): // minutes + formatters_.push_back(details::make_unique(padding)); + break; + + case ('S'): // seconds + formatters_.push_back(details::make_unique(padding)); + break; + + case ('e'): // milliseconds + formatters_.push_back(details::make_unique(padding)); + break; + + case ('f'): // microseconds + formatters_.push_back(details::make_unique(padding)); + break; + + case ('F'): // nanoseconds + formatters_.push_back(details::make_unique(padding)); + break; + + case ('E'): // seconds since epoch + formatters_.push_back(details::make_unique(padding)); + break; + + case ('p'): // am/pm + formatters_.push_back(details::make_unique(padding)); + break; + + case ('r'): // 12 hour clock 02:55:02 pm + formatters_.push_back(details::make_unique(padding)); + break; + + case ('R'): // 24-hour HH:MM time + formatters_.push_back(details::make_unique(padding)); + break; + + case ('T'): + case ('X'): // ISO 8601 time format (HH:MM:SS) + formatters_.push_back(details::make_unique(padding)); + break; + + case ('z'): // timezone + formatters_.push_back(details::make_unique(padding)); + break; + + case ('P'): // pid + formatters_.push_back(details::make_unique(padding)); + break; + + case ('^'): // color range start + formatters_.push_back(details::make_unique(padding)); + break; + + case ('$'): // color range end + formatters_.push_back(details::make_unique(padding)); + break; + + case ('@'): // source location (filename:filenumber) + formatters_.push_back(details::make_unique(padding)); + break; + + case ('s'): // source filename + formatters_.push_back(details::make_unique(padding)); + break; + + case ('#'): // source line number + formatters_.push_back(details::make_unique(padding)); + break; + + case ('!'): // source funcname + formatters_.push_back(details::make_unique(padding)); + break; + + case ('%'): // % char + formatters_.push_back(details::make_unique('%')); + 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. +SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end) +{ + using details::padding_info; + using details::scoped_pad; + const size_t max_width = 128; + if (it == end) + { + return padding_info{}; } - SPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg) + padding_info::pad_side side; + switch (*it) { - if (pattern_time_type_ == pattern_time_type::local) - { - return details::os::localtime(log_clock::to_time_t(msg.time)); - } - return details::os::gmtime(log_clock::to_time_t(msg.time)); + case '-': + side = padding_info::right; + ++it; + break; + case '=': + side = padding_info::center; + ++it; + break; + default: + side = details::padding_info::left; + break; } - SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_info padding) + if (it == end || !std::isdigit(static_cast(*it))) { - switch (flag) - { - - case ('+'): // default formatter - formatters_.push_back(details::make_unique(padding)); - break; - - case 'n': // logger name - formatters_.push_back(details::make_unique(padding)); - break; - - case 'l': // level - formatters_.push_back(details::make_unique(padding)); - break; - - case 'L': // short level - formatters_.push_back(details::make_unique(padding)); - break; - - case ('t'): // thread id - formatters_.push_back(details::make_unique(padding)); - break; - - case ('v'): // the message text - formatters_.push_back(details::make_unique(padding)); - break; - - case ('a'): // weekday - formatters_.push_back(details::make_unique(padding)); - break; - - case ('A'): // short weekday - formatters_.push_back(details::make_unique(padding)); - break; - - case ('b'): - case ('h'): // month - formatters_.push_back(details::make_unique(padding)); - break; - - case ('B'): // short month - formatters_.push_back(details::make_unique(padding)); - break; - - case ('c'): // datetime - formatters_.push_back(details::make_unique(padding)); - break; - - case ('C'): // year 2 digits - formatters_.push_back(details::make_unique(padding)); - break; - - case ('Y'): // year 4 digits - formatters_.push_back(details::make_unique(padding)); - break; - - case ('D'): - case ('x'): // datetime MM/DD/YY - formatters_.push_back(details::make_unique(padding)); - break; - - case ('m'): // month 1-12 - formatters_.push_back(details::make_unique(padding)); - break; - - case ('d'): // day of month 1-31 - formatters_.push_back(details::make_unique(padding)); - break; - - case ('H'): // hours 24 - formatters_.push_back(details::make_unique(padding)); - break; - - case ('I'): // hours 12 - formatters_.push_back(details::make_unique(padding)); - break; - - case ('M'): // minutes - formatters_.push_back(details::make_unique(padding)); - break; - - case ('S'): // seconds - formatters_.push_back(details::make_unique(padding)); - break; - - case ('e'): // milliseconds - formatters_.push_back(details::make_unique(padding)); - break; - - case ('f'): // microseconds - formatters_.push_back(details::make_unique(padding)); - break; - - case ('F'): // nanoseconds - formatters_.push_back(details::make_unique(padding)); - break; - - case ('E'): // seconds since epoch - formatters_.push_back(details::make_unique(padding)); - break; - - case ('p'): // am/pm - formatters_.push_back(details::make_unique(padding)); - break; - - case ('r'): // 12 hour clock 02:55:02 pm - formatters_.push_back(details::make_unique(padding)); - break; - - case ('R'): // 24-hour HH:MM time - formatters_.push_back(details::make_unique(padding)); - break; - - case ('T'): - case ('X'): // ISO 8601 time format (HH:MM:SS) - formatters_.push_back(details::make_unique(padding)); - break; - - case ('z'): // timezone - formatters_.push_back(details::make_unique(padding)); - break; - - case ('P'): // pid - formatters_.push_back(details::make_unique(padding)); - break; - - case ('^'): // color range start - formatters_.push_back(details::make_unique(padding)); - break; - - case ('$'): // color range end - formatters_.push_back(details::make_unique(padding)); - break; - - case ('@'): // source location (filename:filenumber) - formatters_.push_back(details::make_unique(padding)); - break; - - case ('s'): // source filename - formatters_.push_back(details::make_unique(padding)); - break; - - case ('#'): // source line number - formatters_.push_back(details::make_unique(padding)); - break; - - case ('!'): // source funcname - formatters_.push_back(details::make_unique(padding)); - break; - - case ('%'): // % char - formatters_.push_back(details::make_unique('%')); - 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; - } + return padding_info{0, side}; } - // Extract given pad spec (e.g. %8X) - // Advance the given it pass the end of the padding spec found (if any) - // Return padding. - SPDLOG_INLINE details::padding_info pattern_formatter::handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end) + auto width = static_cast(*it - '0'); + for (++it; it != end && std::isdigit(static_cast(*it)); ++it) { - using details::padding_info; - using details::scoped_pad; - const size_t max_width = 128; - 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}; - } - - auto 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}; + auto digit = static_cast(*it - '0'); + width = width * 10 + digit; } + return details::padding_info{std::min(width, max_width), side}; +} - SPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern) +SPDLOG_INLINE void pattern_formatter::compile_pattern_(const std::string &pattern) +{ + auto end = pattern.end(); + std::unique_ptr user_chars; + formatters_.clear(); + for (auto it = pattern.begin(); it != end; ++it) { - auto end = pattern.end(); - std::unique_ptr user_chars; - formatters_.clear(); - for (auto it = pattern.begin(); it != end; ++it) + if (*it == '%') { - if (*it == '%') + if (user_chars) // append user chars found so far { - if (user_chars) // append user chars found so far - { - formatters_.push_back(std::move(user_chars)); - } - - auto padding = handle_padspec_(++it, end); - - if (it != end) - { - handle_flag_(*it, padding); - } - else - { - break; - } + formatters_.push_back(std::move(user_chars)); } - else // chars not following the % sign should be displayed as is + + auto padding = handle_padspec_(++it, end); + + if (it != end) { - if (!user_chars) - { - user_chars = details::make_unique(); - } - user_chars->add_ch(*it); + handle_flag_(*it, padding); + } + else + { + break; } } - if (user_chars) // append raw chars found so far + else // chars not following the % sign should be displayed as is { - formatters_.push_back(std::move(user_chars)); + if (!user_chars) + { + user_chars = details::make_unique(); + } + user_chars->add_ch(*it); } } + if (user_chars) // append raw chars found so far + { + formatters_.push_back(std::move(user_chars)); + } +} } // namespace spdlog - diff --git a/include/spdlog/impl/registry.cpp b/include/spdlog/impl/registry.cpp index b4487b4a..ca0247eb 100644 --- a/include/spdlog/impl/registry.cpp +++ b/include/spdlog/impl/registry.cpp @@ -6,7 +6,6 @@ #include "spdlog/details/registry.h" #endif - #include "spdlog/common.h" #include "spdlog/details/periodic_worker.h" #include "spdlog/logger.h" diff --git a/include/spdlog/impl/sink.cpp b/include/spdlog/impl/sink.cpp index 7f9e84e5..04adb9be 100644 --- a/include/spdlog/impl/sink.cpp +++ b/include/spdlog/impl/sink.cpp @@ -1,29 +1,31 @@ -#include "spdlog/common.h" -#include "spdlog/details/pattern_formatter.h" - -#ifndef SPDLOG_HEADER_ONLY -#include "spdlog/sinks/sink.h" -#endif - -SPDLOG_INLINE spdlog::sinks::sink::sink() - : formatter_{details::make_unique()} -{} - -SPDLOG_INLINE spdlog::sinks::sink::sink(std::unique_ptr formatter) - : formatter_{std::move(formatter)} -{} - -SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const -{ - return msg_level >= level_.load(std::memory_order_relaxed); -} - -SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) -{ - level_.store(log_level); -} - -SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const -{ - return static_cast(level_.load(std::memory_order_relaxed)); -} +#include "spdlog/common.h" +#include "spdlog/details/pattern_formatter.h" + +#ifndef SPDLOG_HEADER_ONLY +#include "spdlog/sinks/sink.h" +#endif + +SPDLOG_INLINE spdlog::sinks::sink::sink() + : formatter_{details::make_unique()} +{ +} + +SPDLOG_INLINE spdlog::sinks::sink::sink(std::unique_ptr formatter) + : formatter_{std::move(formatter)} +{ +} + +SPDLOG_INLINE bool spdlog::sinks::sink::should_log(spdlog::level::level_enum msg_level) const +{ + return msg_level >= level_.load(std::memory_order_relaxed); +} + +SPDLOG_INLINE void spdlog::sinks::sink::set_level(level::level_enum log_level) +{ + level_.store(log_level); +} + +SPDLOG_INLINE spdlog::level::level_enum spdlog::sinks::sink::level() const +{ + return static_cast(level_.load(std::memory_order_relaxed)); +} diff --git a/include/spdlog/logger.h b/include/spdlog/logger.h index 070e9875..91371320 100644 --- a/include/spdlog/logger.h +++ b/include/spdlog/logger.h @@ -33,313 +33,310 @@ namespace spdlog { class logger { public: - template - logger(std::string name, It begin, It end) - : name_(std::move(name)) - , sinks_(begin, end) + template + logger(std::string name, It begin, It end) + : name_(std::move(name)) + , sinks_(begin, end) + { + } + + logger(std::string name, sink_ptr single_sink) + : logger(std::move(name), {std::move(single_sink)}) + { + } + logger(std::string name, sinks_init_list sinks) + : logger(std::move(name), sinks.begin(), sinks.end()) + { + } + + virtual ~logger() = default; + + logger(const logger &) = delete; + logger &operator=(const logger &) = delete; + + template + void log(source_loc loc, level::level_enum lvl, const char *fmt, const Args &... args) + { + if (!should_log(lvl)) { + return; } - logger(std::string name, sink_ptr single_sink) - : logger(std::move(name), {std::move(single_sink)}) + try { + fmt::memory_buffer buf; + fmt::format_to(buf, fmt, args...); + details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); + sink_it_(log_msg); } - logger(std::string name, sinks_init_list sinks) - : logger(std::move(name), sinks.begin(), sinks.end()) + catch (const std::exception &ex) { + err_handler_(ex.what()); } - - virtual ~logger() = default; - - logger(const logger &) = delete; - logger &operator=(const logger &) = delete; - - template - void log(source_loc loc, level::level_enum lvl, const char *fmt, const Args &... args) + catch (...) { - if (!should_log(lvl)) - { - return; - } - - try - { - fmt::memory_buffer buf; - fmt::format_to(buf, fmt, args...); - details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } + err_handler_("Unknown exception in logger"); } + } - template - void log(level::level_enum lvl, const char *fmt, const Args &... args) + template + void log(level::level_enum lvl, const char *fmt, const Args &... args) + { + log(source_loc{}, lvl, fmt, args...); + } + + void log(source_loc loc, level::level_enum lvl, const char *msg); + void log(level::level_enum lvl, const char *msg); + + template + void trace(const char *fmt, const Args &... args) + { + log(level::trace, fmt, args...); + } + + template + void debug(const char *fmt, const Args &... args) + { + log(level::debug, fmt, args...); + } + + template + void info(const char *fmt, const Args &... args) + { + log(level::info, fmt, args...); + } + + template + void warn(const char *fmt, const Args &... args) + { + log(level::warn, fmt, args...); + } + + template + void error(const char *fmt, const Args &... args) + { + log(level::err, fmt, args...); + } + + template + void critical(const char *fmt, const Args &... args) + { + log(level::critical, fmt, args...); + } + + template + void log(level::level_enum lvl, const T &msg) + { + log(source_loc{}, lvl, msg); + } + + // T can be statically converted to string_view + template::value, T>::type * = nullptr> + void log(source_loc loc, level::level_enum lvl, const T &msg) + { + if (!should_log(lvl)) { - log(source_loc{}, lvl, fmt, args...); + return; } - - void log(source_loc loc, level::level_enum lvl, const char *msg); - void log(level::level_enum lvl, const char *msg); - - template - void trace(const char *fmt, const Args &... args) + try { - log(level::trace, fmt, args...); + details::log_msg log_msg(loc, &name_, lvl, msg); + sink_it_(log_msg); } - - template - void debug(const char *fmt, const Args &... args) + catch (const std::exception &ex) { - log(level::debug, fmt, args...); + err_handler_(ex.what()); } - - template - void info(const char *fmt, const Args &... args) + catch (...) { - log(level::info, fmt, args...); + err_handler_("Unknown exception in logger"); } + } - template - void warn(const char *fmt, const Args &... args) + // T cannot be statically converted to string_view + template::value, T>::type * = nullptr> + void log(source_loc loc, level::level_enum lvl, const T &msg) + { + if (!should_log(lvl)) { - log(level::warn, fmt, args...); + return; } - - template - void error(const char *fmt, const Args &... args) + try { - log(level::err, fmt, args...); + fmt::memory_buffer buf; + fmt::format_to(buf, "{}", msg); + details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); + sink_it_(log_msg); } - - template - void critical(const char *fmt, const Args &... args) + catch (const std::exception &ex) { - log(level::critical, fmt, args...); + err_handler_(ex.what()); } - - - template - void log(level::level_enum lvl, const T &msg) + catch (...) { - log(source_loc{}, lvl, msg); + err_handler_("Unknown exception in logger"); } + } - // T can be statically converted to string_view - template::value, T>::type * = nullptr> - void log(source_loc loc, level::level_enum lvl, const T &msg) - { - if (!should_log(lvl)) - { - return; - } - try - { - details::log_msg log_msg(loc, &name_, lvl, msg); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } - } + template + void trace(const T &msg) + { + log(level::trace, msg); + } - // T cannot be statically converted to string_view - template::value, T>::type * = nullptr> - void log(source_loc loc, level::level_enum lvl, const T &msg) - { - if (!should_log(lvl)) - { - return; - } - try - { - fmt::memory_buffer buf; - fmt::format_to(buf, "{}", msg); - details::log_msg log_msg(loc, &name_, lvl, string_view_t(buf.data(), buf.size())); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } - } + template + void debug(const T &msg) + { + log(level::debug, msg); + } - template - void trace(const T &msg) - { - log(level::trace, msg); - } + template + void info(const T &msg) + { + log(level::info, msg); + } - template - void debug(const T &msg) - { - log(level::debug, msg); - } + template + void warn(const T &msg) + { + log(level::warn, msg); + } - template - void info(const T &msg) - { - log(level::info, msg); - } + template + void error(const T &msg) + { + log(level::err, msg); + } - template - void warn(const T &msg) - { - log(level::warn, msg); - } - - template - void error(const T &msg) - { - log(level::err, msg); - } - - template - void critical(const T &msg) - { - log(level::critical, msg); - } + template + void critical(const T &msg) + { + log(level::critical, msg); + } #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT #ifndef _WIN32 #error SPDLOG_WCHAR_TO_UTF8_SUPPORT only supported on windows #else - template - void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args) + template + void log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args) + { + if (!should_log(lvl)) { - if (!should_log(lvl)) - { - return; - } - - try - { - // format to wmemory_buffer and convert to utf8 - fmt::wmemory_buffer wbuf; - fmt::format_to(wbuf, fmt, args...); - fmt::memory_buffer buf; - details::os::wbuf_to_utf8buf(wbuf, buf); - details::log_msg log_msg(source, &name_, lvl, string_view_t(buf.data(), buf.size())); - sink_it_(log_msg); - } - catch (const std::exception &ex) - { - err_handler_(ex.what()); - } - catch (...) - { - err_handler_("Unknown exception in logger"); - } + return; } - template - void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) + try { - log(source_loc{}, lvl, fmt, args...); + // format to wmemory_buffer and convert to utf8 + fmt::wmemory_buffer wbuf; + fmt::format_to(wbuf, fmt, args...); + fmt::memory_buffer buf; + details::os::wbuf_to_utf8buf(wbuf, buf); + details::log_msg log_msg(source, &name_, lvl, string_view_t(buf.data(), buf.size())); + sink_it_(log_msg); } + catch (const std::exception &ex) + { + err_handler_(ex.what()); + } + catch (...) + { + err_handler_("Unknown exception in logger"); + } + } - template - void trace(const wchar_t *fmt, const Args &... args) - { - log(level::trace, fmt, args...); - } + template + void log(level::level_enum lvl, const wchar_t *fmt, const Args &... args) + { + log(source_loc{}, lvl, fmt, args...); + } - template - void debug(const wchar_t *fmt, const Args &... args) - { - log(level::debug, fmt, args...); - } + template + void trace(const wchar_t *fmt, const Args &... args) + { + log(level::trace, fmt, args...); + } - template - void info(const wchar_t *fmt, const Args &... args) - { - log(level::info, fmt, args...); - } + template + void debug(const wchar_t *fmt, const Args &... args) + { + log(level::debug, fmt, args...); + } - template - void warn(const wchar_t *fmt, const Args &... args) - { - log(level::warn, fmt, args...); - } + template + void info(const wchar_t *fmt, const Args &... args) + { + log(level::info, fmt, args...); + } - template - void error(const wchar_t *fmt, const Args &... args) - { - log(level::err, fmt, args...); - } + template + void warn(const wchar_t *fmt, const Args &... args) + { + log(level::warn, fmt, args...); + } - template - void critical(const wchar_t *fmt, const Args &... args) - { - log(level::critical, fmt, args...); - } + template + void error(const wchar_t *fmt, const Args &... args) + { + log(level::err, fmt, args...); + } + + template + void critical(const wchar_t *fmt, const Args &... args) + { + log(level::critical, fmt, args...); + } #endif // _WIN32 -#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT +#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT - bool should_log(level::level_enum msg_level) const; + bool should_log(level::level_enum msg_level) const; - void set_level(level::level_enum log_level); + void set_level(level::level_enum log_level); - static level::level_enum default_level(); + static level::level_enum default_level(); - level::level_enum level() const; + level::level_enum level() const; - const std::string &name() const; + const std::string &name() const; - // set formatting for the sinks in this logger. - // each sink will get a seperate instance of the formatter object. - void set_formatter(std::unique_ptr f); + // set formatting for the sinks in this logger. + // each sink will get a seperate instance of the formatter object. + void set_formatter(std::unique_ptr f); - void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); + void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local); - // flush functions - void flush(); - void flush_on(level::level_enum log_level); - level::level_enum flush_level() const; + // flush functions + void flush(); + void flush_on(level::level_enum log_level); + level::level_enum flush_level() const; - // sinks - const std::vector &sinks() const; + // sinks + const std::vector &sinks() const; - std::vector &sinks(); + std::vector &sinks(); - // error handler - void set_error_handler(err_handler); - - // create new logger with same sinks and configuration. - virtual std::shared_ptr clone(std::string logger_name); + // error handler + void set_error_handler(err_handler); - protected: - virtual void sink_it_(details::log_msg &msg); + // create new logger with same sinks and configuration. + virtual std::shared_ptr clone(std::string logger_name); - virtual void flush_(); - bool should_flush_(const details::log_msg &msg); +protected: + virtual void sink_it_(details::log_msg &msg); - // default error handler. - // print the error to stderr with the max rate of 1 message/minute. - void err_handler_(const std::string &msg); - - const std::string name_; - std::vector sinks_; - spdlog::level_t level_{spdlog::logger::default_level()}; - spdlog::level_t flush_level_{level::off}; - err_handler custom_err_handler_{nullptr}; + virtual void flush_(); + bool should_flush_(const details::log_msg &msg); + // default error handler. + // print the error to stderr with the max rate of 1 message/minute. + void err_handler_(const std::string &msg); + const std::string name_; + std::vector sinks_; + spdlog::level_t level_{spdlog::logger::default_level()}; + spdlog::level_t flush_level_{level::off}; + err_handler custom_err_handler_{nullptr}; }; } // namespace spdlog diff --git a/include/spdlog/sinks/sink.h b/include/spdlog/sinks/sink.h index 8515b041..bfa19e03 100644 --- a/include/spdlog/sinks/sink.h +++ b/include/spdlog/sinks/sink.h @@ -17,7 +17,7 @@ class sink public: sink(); - explicit sink(std::unique_ptr formatter); + explicit sink(std::unique_ptr formatter); virtual ~sink() = default; virtual void log(const details::log_msg &msg) = 0; virtual void flush() = 0; @@ -25,9 +25,9 @@ public: virtual void set_formatter(std::unique_ptr sink_formatter) = 0; bool should_log(level::level_enum msg_level) const; - + void set_level(level::level_enum log_level); - + level::level_enum level() const; protected: diff --git a/include/spdlog/spdlog.h b/include/spdlog/spdlog.h index 0c2589e8..aaa93886 100644 --- a/include/spdlog/spdlog.h +++ b/include/spdlog/spdlog.h @@ -328,7 +328,8 @@ inline void critical(const wchar_t *fmt, const Args &... args) // #define SPDLOG_LOGGER_CALL(logger, level, ...) \ - do { \ + do \ + { \ if (logger->should_log(level)) \ logger->log(spdlog::source_loc{SPDLOG_FILE_BASENAME(__FILE__), __LINE__, SPDLOG_FUNCTION}, level, __VA_ARGS__); \ } while (0) diff --git a/tests/test_misc.cpp b/tests/test_misc.cpp index 5f4c094c..7400dd8f 100644 --- a/tests/test_misc.cpp +++ b/tests/test_misc.cpp @@ -107,7 +107,7 @@ TEST_CASE("clone-logger", "[clone]") cloned->info("Some message 2"); auto test_sink = std::static_pointer_cast(cloned->sinks()[0]); - + spdlog::drop_all(); } @@ -128,7 +128,7 @@ TEST_CASE("clone async", "[clone]") spdlog::details::os::sleep_for_millis(10); - auto test_sink = std::static_pointer_cast(cloned->sinks()[0]); + auto test_sink = std::static_pointer_cast(cloned->sinks()[0]); spdlog::drop_all(); }