cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
thread_logger.hpp
Go to the documentation of this file.
1#pragma once
2#if __cplusplus >= 202002L && defined(__cpp_lib_format)
3# include <format>
4# include <stdexcept> // 用于std::format_error / For std::format_error
5#endif
6#include <atomic>
7#include <condition_variable>
8#include <map>
9#include <mutex>
10#include <queue>
11#include <sstream>
12#include <string>
13#include <thread>
14#include <tuple>
15#include <type_traits>
16#include <unordered_map>
17
19
21
22// 包含对象池 / Include object pool
24
25// #define PROJECT_SOURCE_DIR
26
27// !TODO: Why docxgen doesn't work?
28
30{
31
54template<typename T, typename = void>
55struct CPP_TOOLBOX_EXPORT is_container : std::false_type
56{
57};
58
59template<typename T>
62 std::void_t<typename T::value_type,
63 typename T::iterator,
64 decltype(std::declval<T>().begin()),
65 decltype(std::declval<T>().end())>>
66 : std::true_type
67{
68};
69
84template<typename T>
85inline constexpr bool is_container_v = is_container<T>::value;
86
108template<typename T>
110{
111 template<typename U>
112 static auto test(int) -> std::is_same<decltype(std::declval<std::ostream&>()
113 << std::declval<const U&>()),
114 std::ostream&>;
115
116 template<typename>
117 static auto test(...) -> std::false_type;
118
119 static constexpr bool value = decltype(test<T>(0))::value;
120};
121
137template<typename T>
139
158template<typename T>
160{
161 template<typename U>
162 static auto test(int) -> std::is_same<
163 decltype(std::declval<U>().operator<<(std::declval<std::ostream&>())),
164 std::ostream&>;
165
166 template<typename>
167 static auto test(...) -> std::false_type;
168
169 static constexpr bool value = decltype(test<T>(0))::value;
170};
171
186template<typename T>
188
222{
223public:
233 enum class Level : uint8_t
234 {
235 TRACE,
237 DEBUG,
239 INFO,
240 WARN,
242 ERR,
244 CRITICAL
246 };
247
260 static auto instance() -> thread_logger_t&;
261
274 auto level() -> Level { return level_; }
275
287 auto level_str() -> std::string { return level_to_string(level_); }
288
298 auto set_level(Level level) -> void { level_ = level; }
299
322 {
323 public:
334
350 template<typename... Args>
351 void operator()(const char* format, Args&&... args)
352 {
353 if (level_ < logger_.level()) {
354 return;
355 }
356
357#if __cplusplus >= 202002L && defined(__cpp_lib_format)
358 // C++20: 使用std::format以获得更好的性能和标准合规性 / Use std::format
359 // for better performance and standard compliance
360 try {
361 std::string message = std::format(format, std::forward<Args>(args)...);
362 logger_.enqueue(level_, std::move(message));
363 } catch (const std::format_error& e) {
364 // 优雅地处理潜在的格式错误 / Handle potential format errors gracefully
365 std::string error_message = "[Formatting Error] ";
366 error_message += e.what();
367 error_message += " | Original format: '";
368 error_message += format;
369 error_message += "'";
370 logger_.enqueue(Level::ERR, std::move(error_message));
371 }
372#else
373 // Pre-C++20: 使用现有的自定义format_message实现 / Use the existing custom
374 // format_message implementation
375 std::string message = format_message(format, std::forward<Args>(args)...);
376 logger_.enqueue(level_, std::move(message));
377#endif
378 }
379
380 private:
387 static auto format_message(const char* format) -> std::string
388 {
389 return {format}; // 无参数的简单实现 / Simple implementation for no args
390 }
391
408 template<typename T, typename... Args>
409 auto format_message(const char* format, T&& value, Args&&... args)
410 -> std::string
411 {
412 std::string result;
413 while (*format) {
414 if (*format == '{' && *(format + 1) == '}') {
415 std::stringstream ss;
416 ss << value;
417 result += ss.str();
418 return result
419 + format_message(format + 2, std::forward<Args>(args)...);
420 }
421 result += *format++;
422 }
423 return result;
424 }
425
426 thread_logger_t&
427 logger_;
428 Level level_;
430 };
431
462 {
463 public:
476 thread_logger_t& logger,
477 Level level,
479
488
489 // 删除复制/移动构造函数/赋值运算符 / Deleted copy/move
490 // constructors/assignments
495
500 auto str() -> std::string
501 {
502 return ss_ptr_->str();
503 } // 使用指针 / Use pointer
504
526 template<typename T>
527 auto operator<<(const T& container)
528 -> std::enable_if_t<is_container_v<T> && !has_stream_operator_v<T>,
530 {
531 if (level_ < logger_.level()) {
532 return *this;
533 }
534 *ss_ptr_ << "["; // 使用指针 / Use pointer
535 bool first = true;
536 for (const auto& item : container) {
537 if (!first) {
538 *ss_ptr_ << ", ";
539 }
540 *ss_ptr_ << item; // 使用指针 / Use pointer
541 first = false;
542 }
543 *ss_ptr_ << "]"; // 使用指针 / Use pointer
544 return *this;
545 }
546
566 template<typename... Args>
567 auto operator<<(const std::tuple<Args...>& t) -> thread_stream_logger_t&
568 {
569 if (level_ < logger_.level()) {
570 return *this;
571 }
572 print_tuple(t, std::index_sequence_for<Args...> {});
573 return *this;
574 }
575
583 auto red(const std::string& text) -> thread_stream_logger_t&;
584
592 auto green(const std::string& text) -> thread_stream_logger_t&;
593
601 auto yellow(const std::string& text) -> thread_stream_logger_t&;
602
610 auto bold(const std::string& text) -> thread_stream_logger_t&;
611
628 auto operator<<(const char* value) -> thread_stream_logger_t&
629 {
630 if (level_ < logger_.level()) {
631 return *this;
632 }
633 *ss_ptr_ << value; // 使用指针 / Use pointer
634 return *this;
635 }
636
668 template<typename T>
669 auto operator<<(const T& value)
670 -> std::enable_if_t<has_stream_operator_v<T>, thread_stream_logger_t&>
671 {
672 if (level_ < logger_.level()) {
673 return *this;
674 }
675 *ss_ptr_ << value; // Use pointer
676 return *this;
677 }
678
705 template<typename T>
706 auto operator<<(T&& value)
707 -> std::enable_if_t<!has_stream_operator_v<T>
708 && has_ostream_method_v<T>,
710 {
711 if (level_ < logger_.level()) {
712 return *this;
713 }
714 value.operator<<(*ss_ptr_); // 使用指针 / Use pointer
715 return *this;
716 }
717
743 {
744 *ss_ptr_ << logger.str(); // 使用指针 / Use pointer
745 return *this;
746 }
747
776 template<typename K, typename V>
777 auto operator<<(const std::map<K, V>& map) -> thread_stream_logger_t&
778 {
779 if (level_ < logger_.level()) {
780 return *this;
781 }
782 *ss_ptr_ << "{"; // 使用指针 / Use pointer
783 bool first = true;
784 for (const auto& [key, value] : map) {
785 if (!first) {
786 *ss_ptr_ << ", ";
787 }
788 *ss_ptr_ << key << ": " << value; // 使用指针 / Use pointer
789 first = false;
790 }
791 *ss_ptr_ << "}"; // 使用指针 / Use pointer
792 return *this;
793 }
794
823 template<typename K, typename V>
824 auto operator<<(const std::unordered_map<K, V>& map)
826 {
827 if (level_ < logger_.level())
828 return *this;
829 *ss_ptr_ << "{"; // 使用指针 / Use pointer
830 bool first = true;
831 for (const auto& [key, value] : map) {
832 if (!first)
833 *ss_ptr_ << ", ";
834 *ss_ptr_ << key << ": " << value; // 使用指针 / Use pointer
835 first = false;
836 }
837 *ss_ptr_ << "}"; // 使用指针 / Use pointer
838 return *this;
839 }
840
841 private:
864 template<typename Tuple, size_t... Is>
865 auto print_tuple(const Tuple& t, std::index_sequence<Is...>) -> void
866 {
867 if (level_ < logger_.level()) {
868 return;
869 }
870 *ss_ptr_ << "("; // 使用指针 / Use pointer
871 ((*ss_ptr_ << (Is == 0 ? "" : ", ") << std::get<Is>(t)), ...);
872 *ss_ptr_ << ")"; // 使用指针 / Use pointer
873 }
874
875 thread_logger_t&
876 logger_;
877 Level level_;
878 // 将stringstream存储在从池中获取的unique_ptr中 / Store the stringstream in
879 // a unique_ptr obtained from the pool
881 };
882
895 auto trace_f() -> thread_format_logger_t { return {*this, Level::TRACE}; }
896
909 auto debug_f() -> thread_format_logger_t { return {*this, Level::DEBUG}; }
910
924 auto info_f() -> thread_format_logger_t { return {*this, Level::INFO}; }
925
939 auto warn_f() -> thread_format_logger_t { return {*this, Level::WARN}; }
940
954 auto error_f() -> thread_format_logger_t { return {*this, Level::ERR}; }
955
970 {
971 return {*this, Level::CRITICAL};
972 }
973
988 {
989 return {*this, Level::TRACE, stringstream_pool_};
990 }
991
1005 {
1006 return {*this, Level::DEBUG, stringstream_pool_};
1007 }
1008
1023 {
1024 return {*this, Level::INFO, stringstream_pool_};
1025 }
1026
1041 {
1042 return {*this, Level::WARN, stringstream_pool_};
1043 }
1044
1062 {
1063 return {*this, Level::ERR, stringstream_pool_};
1064 }
1065
1083 {
1084 return {*this, Level::CRITICAL, stringstream_pool_};
1085 }
1086
1108 static void shutdown();
1109
1110private:
1111 // 构造函数保持私有 / Constructor remains private
1113 // 删除复制/移动操作 / Delete copy/move operations
1114 thread_logger_t(const thread_logger_t&) = delete;
1115 auto operator=(const thread_logger_t&) -> thread_logger_t& = delete;
1116 thread_logger_t(thread_logger_t&&) = delete;
1117 auto operator=(thread_logger_t&&) -> thread_logger_t& = delete;
1118
1119 void start();
1120 void stop();
1121 void enqueue(Level level, std::string message);
1122 void processLogs();
1123
1124 static auto level_to_string(Level level) -> std::string;
1125
1126 std::queue<std::pair<Level, std::string>> queue_;
1127 std::mutex queue_mutex_;
1128 std::condition_variable queue_cv_;
1129 // 工作线程成员保持不变 / Worker thread member remains
1130 std::thread worker_;
1131 std::atomic<bool> running_ {false};
1132 Level level_ = Level::INFO;
1133
1134 // 单例模式的静态成员 / Static members for singleton pattern
1135 static std::atomic<thread_logger_t*> instance_ptr_;
1136 static std::mutex instance_mutex_;
1137 static std::atomic<bool> shutdown_called_;
1138
1139 // 添加字符串流池 / Add the stringstream pool
1141};
1142
1143} // namespace toolbox::logger
1144
1319#define LOG_TRACE_F toolbox::logger::thread_logger_t::instance().trace_f()
1320#define LOG_DEBUG_F toolbox::logger::thread_logger_t::instance().debug_f()
1321#define LOG_INFO_F toolbox::logger::thread_logger_t::instance().info_f()
1322#define LOG_WARN_F toolbox::logger::thread_logger_t::instance().warn_f()
1323#define LOG_ERROR_F toolbox::logger::thread_logger_t::instance().error_f()
1324#define LOG_CRITICAL_F toolbox::logger::thread_logger_t::instance().critical_f()
1325
1326#define LOG_TRACE_S toolbox::logger::thread_logger_t::instance().trace_s()
1327#define LOG_DEBUG_S toolbox::logger::thread_logger_t::instance().debug_s()
1328#define LOG_INFO_S toolbox::logger::thread_logger_t::instance().info_s()
1329#define LOG_WARN_S toolbox::logger::thread_logger_t::instance().warn_s()
1330#define LOG_ERROR_S toolbox::logger::thread_logger_t::instance().error_s()
1331#define LOG_CRITICAL_S toolbox::logger::thread_logger_t::instance().critical_s()
1332
1333#define LOG_DEBUG_D(x) \
1334 LOG_DEBUG_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1335 << ") " << x
1336#define LOG_INFO_D(x) \
1337 LOG_INFO_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1338 << ") " << x
1339#define LOG_WARN_D(x) \
1340 LOG_WARN_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1341 << ") " << x
1342#define LOG_ERROR_D(x) \
1343 LOG_ERROR_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1344 << ") " << x
1345#define LOG_CRITICAL_D(x) \
1346 LOG_CRITICAL_S << __FILE__ << ":" << __LINE__ << " (" \
1347 << __CURRENT_FUNCTION__ << ") " << x
Definition object_pool.hpp:100
std::unique_ptr< T, PoolDeleter< T > > PooledObjectPtr
管理池化对象的 unique_ptr 的别名。当超出作用域时自动将对象返回池中/ Alias for a unique_ptr managing a pooled object....
Definition object_pool.hpp:107
基于格式的日志记录器,用于printf风格的消息格式化 / Format-based logger for printf-style message formatting
Definition thread_logger.hpp:322
void operator()(const char *format, Args &&... args)
记录格式化消息 / Log a formatted message
Definition thread_logger.hpp:351
用于格式化输出的线程安全流式日志记录器类 / Thread-safe stream logger class for formatted output
Definition thread_logger.hpp:462
auto operator<<(const std::unordered_map< K, V > &map) -> thread_stream_logger_t &
重载std::unordered_map容器的operator<< / Overload operator<< for std::unordered_map containers
Definition thread_logger.hpp:824
thread_stream_logger_t(thread_stream_logger_t &&)=delete
auto operator<<(T &&value) -> std::enable_if_t<!has_stream_operator_v< T > &&has_ostream_method_v< T >, thread_stream_logger_t & >
重载具有成员operator<<的类型的operator<< / Overload operator<< for types with member operator<<
Definition thread_logger.hpp:706
thread_stream_logger_t & operator=(const thread_stream_logger_t &)=delete
auto operator<<(const T &value) -> std::enable_if_t< has_stream_operator_v< T >, thread_stream_logger_t & >
重载具有ostream operator<<的类型的operator<< / Overload operator<< for types that have an operator<< with an ...
Definition thread_logger.hpp:669
auto operator<<(const std::tuple< Args... > &t) -> thread_stream_logger_t &
重载元组的operator<< / Overload operator<< for tuples
Definition thread_logger.hpp:567
auto operator<<(thread_stream_logger_t &logger) -> thread_stream_logger_t &
重载用于组合日志记录器的operator<< / Overload operator<< for combining loggers
Definition thread_logger.hpp:742
thread_stream_logger_t(const thread_stream_logger_t &)=delete
auto operator<<(const T &container) -> std::enable_if_t< is_container_v< T > &&!has_stream_operator_v< T >, thread_stream_logger_t & >
重载容器的operator<< / Overload operator<< for containers
Definition thread_logger.hpp:527
thread_stream_logger_t & operator=(thread_stream_logger_t &&)=delete
auto str() -> std::string
将记录的消息作为字符串获取 / Get the logged message as a string
Definition thread_logger.hpp:500
auto operator<<(const char *value) -> thread_stream_logger_t &
重载C风格字符串的operator<< / Overload operator<< for C-style strings
Definition thread_logger.hpp:628
auto operator<<(const std::map< K, V > &map) -> thread_stream_logger_t &
重载std::map容器的operator<< / Overload operator<< for std::map containers
Definition thread_logger.hpp:777
具有多个日志级别和格式的线程安全日志类 / Thread-safe logging class with multiple logging levels and formats
Definition thread_logger.hpp:222
auto debug_s() -> thread_stream_logger_t
获取用于DEBUG级别消息的流式日志记录器 / Get a stream logger for DEBUG level messages
Definition thread_logger.hpp:1004
auto debug_f() -> thread_format_logger_t
获取用于DEBUG级别消息的格式化日志记录器 / Get a format logger for DEBUG level messages
Definition thread_logger.hpp:909
auto error_s() -> thread_stream_logger_t
获取用于ERROR级别消息的流式日志记录器 / Get a stream logger for ERROR level messages
Definition thread_logger.hpp:1061
auto set_level(Level level) -> void
设置日志级别 / Set the logging level
Definition thread_logger.hpp:298
auto warn_f() -> thread_format_logger_t
获取用于WARN级别消息的格式化日志记录器 / Get a format logger for WARN level messages
Definition thread_logger.hpp:939
auto critical_s() -> thread_stream_logger_t
获取用于CRITICAL级别消息的流式日志记录器 / Get a stream logger for CRITICAL level messages
Definition thread_logger.hpp:1082
auto level_str() -> std::string
获取当前日志级别的字符串表示 / Get the current logging level as a string
Definition thread_logger.hpp:287
auto trace_f() -> thread_format_logger_t
获取用于TRACE级别消息的格式化日志记录器 / Get a format logger for TRACE level messages
Definition thread_logger.hpp:895
auto level() -> Level
获取当前日志级别 / Get the current logging level
Definition thread_logger.hpp:274
Level
日志级别枚举 / Enumeration of logging levels
Definition thread_logger.hpp:234
auto trace_s() -> thread_stream_logger_t
获取用于TRACE级别消息的流式日志记录器 / Get a stream logger for TRACE level messages
Definition thread_logger.hpp:987
auto info_s() -> thread_stream_logger_t
获取用于INFO级别消息的流式日志记录器 / Get a stream logger for INFO level messages
Definition thread_logger.hpp:1022
auto info_f() -> thread_format_logger_t
获取用于INFO级别消息的格式化日志记录器 / Get a format logger for INFO level messages
Definition thread_logger.hpp:924
auto error_f() -> thread_format_logger_t
获取用于ERROR级别消息的格式化日志记录器 / Get a format logger for ERROR level messages
Definition thread_logger.hpp:954
auto warn_s() -> thread_stream_logger_t
获取用于WARN级别消息的流式日志记录器 / Get a stream logger for WARN level messages
Definition thread_logger.hpp:1040
auto critical_f() -> thread_format_logger_t
获取用于CRITICAL级别消息的格式化日志记录器 / Get a format logger for CRITICAL level messages
Definition thread_logger.hpp:969
#define CPP_TOOLBOX_EXPORT
Definition export.hpp:8
通用的编译器、平台、架构检测和实用宏定义 / Common macros for compiler, platform, architecture detection and utility macro...
Definition thread_logger.hpp:30
constexpr bool has_ostream_method_v
has_ostream_method特征的辅助变量模板 / Helper variable template for has_ostream_method trait
Definition thread_logger.hpp:187
constexpr bool has_stream_operator_v
has_stream_operator特征的辅助变量模板 / Helper variable template for has_stream_operator trait
Definition thread_logger.hpp:138
constexpr bool is_container_v
is_container特征的辅助变量模板 / Helper variable template for is_container trait
Definition thread_logger.hpp:85
检查类型是否具有ostream方法的类型特征 / Type trait to check if a type has an ostream method
Definition thread_logger.hpp:160
static auto test(int) -> std::is_same< decltype(std::declval< U >().operator<<(std::declval< std::ostream & >())), std::ostream & >
static auto test(...) -> std::false_type
检查类型是否具有流插入运算符(<<)的类型特征 / Type trait to check if a type has stream insertion operator (<<)
Definition thread_logger.hpp:110
static auto test(int) -> std::is_same< decltype(std::declval< std::ostream & >()<< std::declval< const U & >()), std::ostream & >
static auto test(...) -> std::false_type
检查类型是否为容器的类型特征 / Type trait to check if a type is a container
Definition thread_logger.hpp:56