类图
对象的引用
- 获取静态对象的引用
1 2 |
SPDLOG_API std::shared_ptr<spdlog::logger> &default_logger(); SPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logger); |
1 2 3 4 5 6 7 8 9 10 |
SPDLOG_INLINE std::shared_ptr<spdlog::logger> &default_logger() { static auto s_default_logger = stdout_color_mt(""); return s_default_logger; } SPDLOG_INLINE void set_default_logger(std::shared_ptr<spdlog::logger> new_logger) { default_logger() = std::move(new_logger); } |
- 构造目标对象
1 2 3 4 5 |
template<typename Factory> SPDLOG_INLINE std::shared_ptr<logger> stdout_color_mt(const std::string &logger_name, color_mode mode) { return Factory::template create<sinks::stdout_color_sink_mt>(logger_name, mode); } |
1 2 3 4 5 6 7 |
using default_factory = synchronous_factory; template<typename Sink, typename... SinkArgs> inline std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&...sink_args) { return default_factory::create<Sink>(std::move(logger_name), std::forward<SinkArgs>(sink_args)...); } |
1 2 3 4 5 6 7 8 9 10 11 |
class logger; struct synchronous_factory { template<typename Sink, typename... SinkArgs> static std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs &&... args) { auto sink = std::make_shared<Sink>(std::forward<SinkArgs>(args)...); return std::make_shared<spdlog::logger>(std::move(logger_name), std::move(sink)); } }; |
formatter
- 基类
1 2 3 4 5 6 7 |
class formatter { public: virtual ~formatter() = default; virtual void format(const details::log_msg &msg, memory_buf_t &dest) = 0; virtual std::unique_ptr<formatter> clone() const = 0; }; |
default_formatter
- 派生类:消息构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
template <typename T> class buffer { private: T* ptr_; size_t size_; size_t capacity_; // ... } template <typename T, size_t SIZE = inline_buffer_size, typename Allocator = std::allocator<T>> class basic_memory_buffer final : public detail::buffer<T> { // ... } |
1 2 3 4 5 6 7 |
#ifdef SPDLOG_USE_STD_FORMAT using memory_buf_t = std::string; // ... #else // use fmt lib instead of std::format using memory_buf_t = fmt::basic_memory_buffer<char, 250>; // ... #endif |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
class default_formatter final : public formatter { public: default_formatter() = default; ~default_formatter() = default; std::unique_ptr<formatter> clone() const override { return details::make_unique<default_formatter>(); } void format(const details::log_msg &msg, memory_buf_t &dest) override { using std::chrono::duration_cast; using std::chrono::milliseconds; using std::chrono::seconds; // cache the date/time part for the next second. auto duration = msg.time.time_since_epoch(); auto secs = duration_cast<seconds>(duration); //[2021-08-23 00:57:12.310] [info] Welcome to spdlog version 1.9.2 ! if (cache_timestamp_ != secs || cached_datetime_.size() == 0) { auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time)); cached_datetime_.clear(); cached_datetime_.push_back('['); details::fmt_helper::append_int(tm_time.tm_year + 1900, cached_datetime_); cached_datetime_.push_back('-'); details::fmt_helper::pad2(tm_time.tm_mon + 1, cached_datetime_); cached_datetime_.push_back('-'); details::fmt_helper::pad2(tm_time.tm_mday, cached_datetime_); cached_datetime_.push_back(' '); details::fmt_helper::pad2(tm_time.tm_hour, cached_datetime_); cached_datetime_.push_back(':'); details::fmt_helper::pad2(tm_time.tm_min, cached_datetime_); cached_datetime_.push_back(':'); details::fmt_helper::pad2(tm_time.tm_sec, cached_datetime_); cached_datetime_.push_back('.'); cache_timestamp_ = secs; } dest.append(cached_datetime_.begin(), cached_datetime_.end()); auto millis = details::fmt_helper::time_fraction<milliseconds>(msg.time); details::fmt_helper::pad3(static_cast<uint32_t>(millis.count()), dest); dest.push_back(']'); dest.push_back(' '); // append logger name if exists if (msg.logger_name.size() > 0) { dest.push_back('['); details::fmt_helper::append_string_view(msg.logger_name, dest); dest.push_back(']'); dest.push_back(' '); } dest.push_back('['); // wrap the level name with color msg.color_range_start = dest.size(); // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); details::fmt_helper::append_string_view(level::to_string_view(msg.level), dest); msg.color_range_end = dest.size(); dest.push_back(']'); dest.push_back(' '); // add source location if present if (!msg.source.empty()) { dest.push_back('['); // const char *filename = details::short_filename_formatter<details::null_scoped_padder>::basename(msg.source.filename); // details::fmt_helper::append_string_view(filename, dest); dest.push_back(':'); details::fmt_helper::append_int(msg.source.line, dest); dest.push_back(']'); dest.push_back(' '); } details::fmt_helper::append_string_view(msg.payload, dest); details::fmt_helper::append_string_view(details::os::default_eol, dest); } private: std::chrono::seconds cache_timestamp_{0}; memory_buf_t cached_datetime_; }; |
pattern_formatter
- 派生类
wincolor_sink
GetConsoleMode
可以帮助获取控制台的输入模式和输出模式的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_color_mode_impl(color_mode mode) { if (mode == color_mode::automatic) { // should do colors only if out_handle_ points to actual console. DWORD console_mode; bool in_console = ::GetConsoleMode(static_cast<HANDLE>(out_handle_), &console_mode) != 0; should_do_colors_ = in_console; } else { should_do_colors_ = mode == color_mode::always ? true : false; } } |
GetConsoleScreenBufferInfo
可以帮助获取控制台屏幕缓冲区的状态信息,如缓冲区的尺寸、光标位置、文本属性SetConsoleTextAttribute
是一个 Win32 API 函数,用于设置控制台屏幕缓冲区中字符的文本属性,包括前景色和背景色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
template<typename ConsoleMutex> std::uint16_t SPDLOG_INLINE wincolor_sink<ConsoleMutex>::set_foreground_color_(std::uint16_t attribs) { CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info; if (!::GetConsoleScreenBufferInfo(static_cast<HANDLE>(out_handle_), &orig_buffer_info)) { // just return white if failed getting console info return FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; } // change only the foreground bits (lowest 4 bits) auto new_attribs = static_cast<WORD>(attribs) | (orig_buffer_info.wAttributes & 0xfff0); auto ignored = ::SetConsoleTextAttribute(static_cast<HANDLE>(out_handle_), static_cast<WORD>(new_attribs)); (void)(ignored); return static_cast<std::uint16_t>(orig_buffer_info.wAttributes); // return orig attribs } |
WriteConsoleA
是一个 Win32 API 函数,用于向控制台屏幕缓冲区写入字符或字符串,并将其显示在控制台上
1 2 3 4 5 6 7 8 9 10 |
template<typename ConsoleMutex> void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::print_range_(const memory_buf_t &formatted, size_t start, size_t end) { if (end > start) { auto size = static_cast<DWORD>(end - start); auto ignored = ::WriteConsoleA(static_cast<HANDLE>(out_handle_), formatted.data() + start, size, nullptr, nullptr); (void)(ignored); } } |
GetStdHandle
是一个 Win32 API 函数,用于获取标准输入、标准输出和标准错误的句柄- 在 Windows 操作系统中,每个进程都有三个标准的输入输出句柄,分别对应标准输入设备、标准输出设备和标准错误设备
1 2 3 4 5 |
// WinBase.h #define STD_INPUT_HANDLE ((DWORD)-10) #define STD_OUTPUT_HANDLE ((DWORD)-11) #define STD_ERROR_HANDLE ((DWORD)-12) |
1 2 3 4 5 6 |
// wincolor_sink(void *out_handle, color_mode mode); template<typename ConsoleMutex> SPDLOG_INLINE wincolor_stdout_sink<ConsoleMutex>::wincolor_stdout_sink(color_mode mode) : wincolor_sink<ConsoleMutex>(::GetStdHandle(STD_OUTPUT_HANDLE), mode) {} |
msvc_sink
OutputDebugStringA
是一个 Windows API 函数,用于将字符串输出到调试输出窗口- 在 Windows 系统中,调试输出窗口通常由调试器或调试工具来监视应用程序的输出,开发人员可以使用
OutputDebugStringA
函数在调试输出窗口中输出调试信息
1 2 3 4 5 6 7 8 9 10 |
void sink_it_(const details::log_msg &msg) override { memory_buf_t formatted; base_sink<Mutex>::formatter_->format(msg, formatted); # ifdef SPDLOG_USE_STD_FORMAT OutputDebugStringA(formatted.c_str()); # else OutputDebugStringA(fmt::to_string(formatted).c_str()); # endif } |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Effective C++_第二篇07/01
- ♥ C++并发编程 _ 共享数据05/16
- ♥ Soui六06/01
- ♥ Soui三05/19
- ♥ 51CTO:Linux C++网络编程一08/13
- ♥ Soui二05/18