提示信息

构建高效、线程安全的C++简易日志系统

延长线 已关注

构建一个高效、线程安全的C++简易日志系统涉及多个方面,包括日志输出、文件写入、格式控制以及线程安全性。同时,保持系统的简洁和易于使用也是重要的。下面是一个基本的设计实现思路,包括代码样例:

基本思路

  1. 日志级别控制:支持不同的日志级别(如INFO, DEBUG, WARNING, ERROR)。
  2. 线程安全性:使用互斥锁或其他同步机制确保多线程环境下的安全性。
  3. 异步日志记录:使用队列和后台线程将日志记录与应用程序主线程解耦,以提高性能。
  4. 日志格式:支持时间戳、日志级别、源文件名、行号等信息。
  5. 配置和扩展性:允许用户配置日志输出位置、日志级别等。

代码实现

  1. #include <iostream>
  2. #include <fstream>
  3. #include <sstream>
  4. #include <string>
  5. #include <mutex>
  6. #include <thread>
  7. #include <queue>
  8. #include <condition_variable>
  9. #include <atomic>
  10. #include <chrono>
  11. enum class LogLevel {
  12. INFO,
  13. DEBUG,
  14. WARNING,
  15. ERROR
  16. };
  17. class Logger {
  18. public:
  19. Logger(const std::string& filename) : logFile(filename), exitFlag(false) {
  20. logThread = std::thread(&Logger::processEntries, this);
  21. }
  22. ~Logger() {
  23. {
  24. std::lock_guard<std::mutex> lock(queueMutex);
  25. exitFlag = true;
  26. queueCondVar.notify_one();
  27. }
  28. if (logThread.joinable()) {
  29. logThread.join();
  30. }
  31. }
  32. void log(LogLevel level, const std::string& message, const char* file, int line) {
  33. std::stringstream ss;
  34. ss << "[" << currentDateTime() << "] "
  35. << "[" << logLevelToString(level) << "] "
  36. << "[" << file << ":" << line << "] "
  37. << message << "\n";
  38. {
  39. std::lock_guard<std::mutex> lock(queueMutex);
  40. logQueue.push(ss.str());
  41. }
  42. queueCondVar.notify_one();
  43. }
  44. private:
  45. std::ofstream logFile;
  46. std::thread logThread;
  47. std::mutex queueMutex;
  48. std::condition_variable queueCondVar;
  49. std::queue<std::string> logQueue;
  50. std::atomic<bool> exitFlag;
  51. void processEntries() {
  52. while (true) {
  53. std::unique_lock<std::mutex> lock(queueMutex);
  54. queueCondVar.wait(lock, [this] { return !logQueue.empty() || exitFlag; });
  55. while (!logQueue.empty()) {
  56. logFile << logQueue.front();
  57. logQueue.pop();
  58. }
  59. if (exitFlag) break;
  60. }
  61. }
  62. std::string logLevelToString(LogLevel level) {
  63. switch (level) {
  64. case LogLevel::INFO: return "INFO";
  65. case LogLevel::DEBUG: return "DEBUG";
  66. case LogLevel::WARNING: return "WARNING";
  67. case LogLevel::ERROR: return "ERROR";
  68. default: return "UNKNOWN";
  69. }
  70. }
  71. std::string currentDateTime() {
  72. std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
  73. char buf[100] = {0};
  74. std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", std::localtime(&now));
  75. return buf;
  76. }
  77. };
  78. // Usage example with a simple logging macro
  79. #define LOG(level, message) LoggerInstance.log(level, message, __FILE__, __LINE__)
  80. int main() {
  81. Logger LoggerInstance("log.txt");
  82. LOG(LogLevel::INFO, "This is an info message");
  83. LOG(LogLevel::DEBUG, "Debugging the application");
  84. LOG(LogLevel::WARNING, "This is a warning");
  85. LOG(LogLevel::ERROR, "An error occurred");
  86. return 0;
  87. }

说明

  • LogLevel: 使用枚举表示不同的日志级别。
  • Logger类: 负责日志文件的打开和写入,使用线程和条件变量实现异步日志处理。
  • log方法: 将日志消息格式化并加入队列。
  • processEntries方法: 由独立线程运行,负责从队列中取出日志并写入文件。
  • 线程安全: 使用std::mutexstd::condition_variable确保队列操作的线程安全性。
  • 日志格式: 包含时间、级别、文件名和行号的信息。

这个系统提供了一个简单高效的日志解决方案,在需要时可以扩展或调整以满足更复杂的需求。

    遇到难题? "AI大模型GPT4.0、GPT" 是你的私人解答专家! 点击按钮去提问......
延长线 关注 已关注

最近一次登录:2024-11-19 23:02:12   

暂时还没有签名,请关注我或评论我的文章
×
免费图表工具,画流程图、架构图