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
18#include <cpp-toolbox/cpp-toolbox_export.hpp>
19
20#include "cpp-toolbox/macro.hpp"
21
22// 包含并发队列头文件 / Include the concurrent queue header
24
25// 包含对象池 / Include object pool
27
28// #define PROJECT_SOURCE_DIR
29
30// !TODO: Why docxgen doesn't work?
31
33{
34
57template<typename T, typename = void>
58struct CPP_TOOLBOX_EXPORT is_container : std::false_type
59{
60};
61
62template<typename T>
63struct CPP_TOOLBOX_EXPORT
65 std::void_t<typename T::value_type,
66 typename T::iterator,
67 decltype(std::declval<T>().begin()),
68 decltype(std::declval<T>().end())>>
69 : std::true_type
70{
71};
72
87template<typename T>
88inline constexpr bool is_container_v = is_container<T>::value;
89
111template<typename T>
112struct CPP_TOOLBOX_EXPORT has_stream_operator
113{
114 template<typename U>
115 static auto test(int) -> std::is_same<decltype(std::declval<std::ostream&>()
116 << std::declval<const U&>()),
117 std::ostream&>;
118
119 template<typename>
120 static auto test(...) -> std::false_type;
121
122 static constexpr bool value = decltype(test<T>(0))::value;
123};
124
140template<typename T>
142
161template<typename T>
162struct CPP_TOOLBOX_EXPORT has_ostream_method
163{
164 template<typename U>
165 static auto test(int) -> std::is_same<
166 decltype(std::declval<U>().operator<<(std::declval<std::ostream&>())),
167 std::ostream&>;
168
169 template<typename>
170 static auto test(...) -> std::false_type;
171
172 static constexpr bool value = decltype(test<T>(0))::value;
173};
174
189template<typename T>
191
224class CPP_TOOLBOX_EXPORT thread_logger_t
225{
226public:
236 enum class Level : uint8_t
237 {
238 TRACE,
240 DEBUG,
242 INFO,
243 WARN,
245 ERR,
247 CRITICAL
249 };
250
263 static auto instance() -> thread_logger_t&;
264
277 auto level() -> Level { return level_; }
278
290 auto level_str() -> std::string { return level_to_string(level_); }
291
301 auto set_level(Level level) -> void { level_ = level; }
302
324 class CPP_TOOLBOX_EXPORT thread_format_logger_t
325 {
326 public:
337
353 template<typename... Args>
354 void operator()(const char* format, Args&&... args)
355 {
356 if (level_ < logger_.level()) {
357 return;
358 }
359
360#if __cplusplus >= 202002L && defined(__cpp_lib_format)
361 // C++20: 使用std::format以获得更好的性能和标准合规性 / Use std::format
362 // for better performance and standard compliance
363 try {
364 std::string message = std::format(format, std::forward<Args>(args)...);
365 logger_.enqueue(level_, std::move(message));
366 } catch (const std::format_error& e) {
367 // 优雅地处理潜在的格式错误 / Handle potential format errors gracefully
368 std::string error_message = "[Formatting Error] ";
369 error_message += e.what();
370 error_message += " | Original format: '";
371 error_message += format;
372 error_message += "'";
373 logger_.enqueue(Level::ERR, std::move(error_message));
374 }
375#else
376 // Pre-C++20: 使用现有的自定义format_message实现 / Use the existing custom
377 // format_message implementation
378 std::string message = format_message(format, std::forward<Args>(args)...);
379 logger_.enqueue(level_, std::move(message));
380#endif
381 }
382
383 private:
390 static auto format_message(const char* format) -> std::string
391 {
392 return {format}; // 无参数的简单实现 / Simple implementation for no args
393 }
394
411 template<typename T, typename... Args>
412 auto format_message(const char* format, T&& value, Args&&... args)
413 -> std::string
414 {
415 std::string result;
416 while (*format) {
417 if (*format == '{' && *(format + 1) == '}') {
418 std::stringstream ss;
419 ss << value;
420 result += ss.str();
421 return result
422 + format_message(format + 2, std::forward<Args>(args)...);
423 }
424 result += *format++;
425 }
426 return result;
427 }
428
429 thread_logger_t&
430 logger_;
431 Level level_;
433 };
434
464 class CPP_TOOLBOX_EXPORT thread_stream_logger_t
465 {
466 public:
479 thread_logger_t& logger,
480 Level level,
482
491
492 // 删除复制/移动构造函数/赋值运算符 / Deleted copy/move
493 // constructors/assignments
498
503 auto str() -> std::string
504 {
505 return ss_ptr_->str();
506 } // 使用指针 / Use pointer
507
529 template<typename T>
530 auto operator<<(const T& container)
531 -> std::enable_if_t<is_container_v<T> && !has_stream_operator_v<T>,
533 {
534 if (level_ < logger_.level()) {
535 return *this;
536 }
537 *ss_ptr_ << "["; // 使用指针 / Use pointer
538 bool first = true;
539 for (const auto& item : container) {
540 if (!first) {
541 *ss_ptr_ << ", ";
542 }
543 *ss_ptr_ << item; // 使用指针 / Use pointer
544 first = false;
545 }
546 *ss_ptr_ << "]"; // 使用指针 / Use pointer
547 return *this;
548 }
549
569 template<typename... Args>
570 auto operator<<(const std::tuple<Args...>& t) -> thread_stream_logger_t&
571 {
572 if (level_ < logger_.level()) {
573 return *this;
574 }
575 print_tuple(t, std::index_sequence_for<Args...> {});
576 return *this;
577 }
578
586 auto red(const std::string& text) -> thread_stream_logger_t&;
587
595 auto green(const std::string& text) -> thread_stream_logger_t&;
596
604 auto yellow(const std::string& text) -> thread_stream_logger_t&;
605
613 auto bold(const std::string& text) -> thread_stream_logger_t&;
614
631 auto operator<<(const char* value) -> thread_stream_logger_t&
632 {
633 if (level_ < logger_.level()) {
634 return *this;
635 }
636 *ss_ptr_ << value; // 使用指针 / Use pointer
637 return *this;
638 }
639
671 template<typename T>
672 auto operator<<(const T& value)
673 -> std::enable_if_t<has_stream_operator_v<T>, thread_stream_logger_t&>
674 {
675 if (level_ < logger_.level()) {
676 return *this;
677 }
678 *ss_ptr_ << value; // Use pointer
679 return *this;
680 }
681
708 template<typename T>
709 auto operator<<(T&& value)
710 -> std::enable_if_t<!has_stream_operator_v<T>
711 && has_ostream_method_v<T>,
713 {
714 if (level_ < logger_.level()) {
715 return *this;
716 }
717 value.operator<<(*ss_ptr_); // 使用指针 / Use pointer
718 return *this;
719 }
720
746 {
747 *ss_ptr_ << logger.str(); // 使用指针 / Use pointer
748 return *this;
749 }
750
779 template<typename K, typename V>
780 auto operator<<(const std::map<K, V>& map) -> thread_stream_logger_t&
781 {
782 if (level_ < logger_.level()) {
783 return *this;
784 }
785 *ss_ptr_ << "{"; // 使用指针 / Use pointer
786 bool first = true;
787 for (const auto& [key, value] : map) {
788 if (!first) {
789 *ss_ptr_ << ", ";
790 }
791 *ss_ptr_ << key << ": " << value; // 使用指针 / Use pointer
792 first = false;
793 }
794 *ss_ptr_ << "}"; // 使用指针 / Use pointer
795 return *this;
796 }
797
826 template<typename K, typename V>
827 auto operator<<(const std::unordered_map<K, V>& map)
829 {
830 if (level_ < logger_.level())
831 return *this;
832 *ss_ptr_ << "{"; // 使用指针 / Use pointer
833 bool first = true;
834 for (const auto& [key, value] : map) {
835 if (!first)
836 *ss_ptr_ << ", ";
837 *ss_ptr_ << key << ": " << value; // 使用指针 / Use pointer
838 first = false;
839 }
840 *ss_ptr_ << "}"; // 使用指针 / Use pointer
841 return *this;
842 }
843
844 private:
867 template<typename Tuple, size_t... Is>
868 auto print_tuple(const Tuple& t, std::index_sequence<Is...>) -> void
869 {
870 if (level_ < logger_.level()) {
871 return;
872 }
873 *ss_ptr_ << "("; // 使用指针 / Use pointer
874 ((*ss_ptr_ << (Is == 0 ? "" : ", ") << std::get<Is>(t)), ...);
875 *ss_ptr_ << ")"; // 使用指针 / Use pointer
876 }
877
878 thread_logger_t&
879 logger_;
880 Level level_;
881 // 将stringstream存储在从池中获取的unique_ptr中 / Store the stringstream in
882 // a unique_ptr obtained from the pool
884 };
885
898 auto trace_f() -> thread_format_logger_t { return {*this, Level::TRACE}; }
899
912 auto debug_f() -> thread_format_logger_t { return {*this, Level::DEBUG}; }
913
927 auto info_f() -> thread_format_logger_t { return {*this, Level::INFO}; }
928
942 auto warn_f() -> thread_format_logger_t { return {*this, Level::WARN}; }
943
957 auto error_f() -> thread_format_logger_t { return {*this, Level::ERR}; }
958
973 {
974 return {*this, Level::CRITICAL};
975 }
976
991 {
992 return {*this, Level::TRACE, stringstream_pool_};
993 }
994
1008 {
1009 return {*this, Level::DEBUG, stringstream_pool_};
1010 }
1011
1026 {
1027 return {*this, Level::INFO, stringstream_pool_};
1028 }
1029
1044 {
1045 return {*this, Level::WARN, stringstream_pool_};
1046 }
1047
1065 {
1066 return {*this, Level::ERR, stringstream_pool_};
1067 }
1068
1086 {
1087 return {*this, Level::CRITICAL, stringstream_pool_};
1088 }
1089
1111 static void shutdown();
1112
1113private:
1114 // 构造函数保持私有 / Constructor remains private
1116 // 删除复制/移动操作 / Delete copy/move operations
1117 thread_logger_t(const thread_logger_t&) = delete;
1118 auto operator=(const thread_logger_t&) -> thread_logger_t& = delete;
1119 thread_logger_t(thread_logger_t&&) = delete;
1120 auto operator=(thread_logger_t&&) -> thread_logger_t& = delete;
1121
1122 void start();
1123 void stop();
1124 void enqueue(Level level, std::string message);
1125 void processLogs();
1126
1127 static auto level_to_string(Level level) -> std::string;
1128
1129 // 队列成员保持不变 / Queue member remains
1131 // 工作线程成员保持不变 / Worker thread member remains
1132 std::thread worker_;
1133 std::atomic<bool> running_ {false};
1134 Level level_ = Level::INFO;
1135
1136 // 单例模式的静态成员 / Static members for singleton pattern
1137 static std::atomic<thread_logger_t*> instance_ptr_;
1138 static std::mutex instance_mutex_;
1139 static std::atomic<bool> shutdown_called_;
1140
1141 // 添加字符串流池 / Add the stringstream pool
1143};
1144
1145} // namespace toolbox::logger
1146
1321#define LOG_TRACE_F toolbox::logger::thread_logger_t::instance().trace_f()
1322#define LOG_DEBUG_F toolbox::logger::thread_logger_t::instance().debug_f()
1323#define LOG_INFO_F toolbox::logger::thread_logger_t::instance().info_f()
1324#define LOG_WARN_F toolbox::logger::thread_logger_t::instance().warn_f()
1325#define LOG_ERROR_F toolbox::logger::thread_logger_t::instance().error_f()
1326#define LOG_CRITICAL_F toolbox::logger::thread_logger_t::instance().critical_f()
1327
1328#define LOG_TRACE_S toolbox::logger::thread_logger_t::instance().trace_s()
1329#define LOG_DEBUG_S toolbox::logger::thread_logger_t::instance().debug_s()
1330#define LOG_INFO_S toolbox::logger::thread_logger_t::instance().info_s()
1331#define LOG_WARN_S toolbox::logger::thread_logger_t::instance().warn_s()
1332#define LOG_ERROR_S toolbox::logger::thread_logger_t::instance().error_s()
1333#define LOG_CRITICAL_S toolbox::logger::thread_logger_t::instance().critical_s()
1334
1335#define LOG_DEBUG_D(x) \
1336 LOG_DEBUG_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1337 << ") " << x
1338#define LOG_INFO_D(x) \
1339 LOG_INFO_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1340 << ") " << x
1341#define LOG_WARN_D(x) \
1342 LOG_WARN_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1343 << ") " << x
1344#define LOG_ERROR_D(x) \
1345 LOG_ERROR_S << __FILE__ << ":" << __LINE__ << " (" << __CURRENT_FUNCTION__ \
1346 << ") " << x
1347#define LOG_CRITICAL_D(x) \
1348 LOG_CRITICAL_S << __FILE__ << ":" << __LINE__ << " (" \
1349 << __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
高性能MPMC并发队列的包装器/A wrapper around a high-performance MPMC concurrent queue
Definition concurrent_queue.hpp:57
基于格式的日志记录器,用于printf风格的消息格式化 / Format-based logger for printf-style message formatting
Definition thread_logger.hpp:325
void operator()(const char *format, Args &&... args)
记录格式化消息 / Log a formatted message
Definition thread_logger.hpp:354
thread_format_logger_t(thread_logger_t &logger, Level level)
使用特定日志级别构造格式日志记录器 / Construct a format logger with a specific logging level
用于格式化输出的线程安全流式日志记录器类 / Thread-safe stream logger class for formatted output
Definition thread_logger.hpp:465
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:827
auto yellow(const std::string &text) -> thread_stream_logger_t &
以黄色格式化文本 / Format text in yellow color
auto red(const std::string &text) -> thread_stream_logger_t &
以红色格式化文本 / Format text in red color
~thread_stream_logger_t()
销毁线程流日志记录器对象 / Destroy the thread stream logger object
auto bold(const std::string &text) -> thread_stream_logger_t &
以粗体格式化文本 / Format text in bold style
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:709
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:672
auto operator<<(const std::tuple< Args... > &t) -> thread_stream_logger_t &
重载元组的operator<< / Overload operator<< for tuples
Definition thread_logger.hpp:570
auto operator<<(thread_stream_logger_t &logger) -> thread_stream_logger_t &
重载用于组合日志记录器的operator<< / Overload operator<< for combining loggers
Definition thread_logger.hpp:745
thread_stream_logger_t(const thread_stream_logger_t &)=delete
auto green(const std::string &text) -> thread_stream_logger_t &
以绿色格式化文本 / Format text in green color
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:530
thread_stream_logger_t(thread_logger_t &logger, Level level, toolbox::base::object_pool_t< std::stringstream > &pool)
使用池构造新的线程流日志记录器对象 / Construct a new thread stream logger object using the pool
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:503
auto operator<<(const char *value) -> thread_stream_logger_t &
重载C风格字符串的operator<< / Overload operator<< for C-style strings
Definition thread_logger.hpp:631
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:780
具有多个日志级别和格式的线程安全日志类 / Thread-safe logging class with multiple logging levels and formats
Definition thread_logger.hpp:225
static void shutdown()
显式关闭日志记录器实例的工作线程 / Explicitly shuts down the logger instance's worker thread
auto debug_s() -> thread_stream_logger_t
获取用于DEBUG级别消息的流式日志记录器 / Get a stream logger for DEBUG level messages
Definition thread_logger.hpp:1007
auto debug_f() -> thread_format_logger_t
获取用于DEBUG级别消息的格式化日志记录器 / Get a format logger for DEBUG level messages
Definition thread_logger.hpp:912
auto error_s() -> thread_stream_logger_t
获取用于ERROR级别消息的流式日志记录器 / Get a stream logger for ERROR level messages
Definition thread_logger.hpp:1064
auto set_level(Level level) -> void
设置日志级别 / Set the logging level
Definition thread_logger.hpp:301
auto warn_f() -> thread_format_logger_t
获取用于WARN级别消息的格式化日志记录器 / Get a format logger for WARN level messages
Definition thread_logger.hpp:942
auto critical_s() -> thread_stream_logger_t
获取用于CRITICAL级别消息的流式日志记录器 / Get a stream logger for CRITICAL level messages
Definition thread_logger.hpp:1085
auto level_str() -> std::string
获取当前日志级别的字符串表示 / Get the current logging level as a string
Definition thread_logger.hpp:290
auto trace_f() -> thread_format_logger_t
获取用于TRACE级别消息的格式化日志记录器 / Get a format logger for TRACE level messages
Definition thread_logger.hpp:898
auto level() -> Level
获取当前日志级别 / Get the current logging level
Definition thread_logger.hpp:277
Level
日志级别枚举 / Enumeration of logging levels
Definition thread_logger.hpp:237
auto trace_s() -> thread_stream_logger_t
获取用于TRACE级别消息的流式日志记录器 / Get a stream logger for TRACE level messages
Definition thread_logger.hpp:990
auto info_s() -> thread_stream_logger_t
获取用于INFO级别消息的流式日志记录器 / Get a stream logger for INFO level messages
Definition thread_logger.hpp:1025
static auto instance() -> thread_logger_t &
获取日志记录器的单例实例 / Get the singleton instance of the logger
auto info_f() -> thread_format_logger_t
获取用于INFO级别消息的格式化日志记录器 / Get a format logger for INFO level messages
Definition thread_logger.hpp:927
auto error_f() -> thread_format_logger_t
获取用于ERROR级别消息的格式化日志记录器 / Get a format logger for ERROR level messages
Definition thread_logger.hpp:957
auto warn_s() -> thread_stream_logger_t
获取用于WARN级别消息的流式日志记录器 / Get a stream logger for WARN level messages
Definition thread_logger.hpp:1043
auto critical_f() -> thread_format_logger_t
获取用于CRITICAL级别消息的格式化日志记录器 / Get a format logger for CRITICAL level messages
Definition thread_logger.hpp:972
通用的编译器、平台、架构检测和实用宏定义 / Common macros for compiler, platform, architecture detection and utility macro...
Definition thread_logger.hpp:33
constexpr bool has_ostream_method_v
has_ostream_method特征的辅助变量模板 / Helper variable template for has_ostream_method trait
Definition thread_logger.hpp:190
constexpr bool has_stream_operator_v
has_stream_operator特征的辅助变量模板 / Helper variable template for has_stream_operator trait
Definition thread_logger.hpp:141
constexpr bool is_container_v
is_container特征的辅助变量模板 / Helper variable template for is_container trait
Definition thread_logger.hpp:88
检查类型是否具有ostream方法的类型特征 / Type trait to check if a type has an ostream method
Definition thread_logger.hpp:163
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:113
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:59