📟作者主頁:慢熱的陜西人
🌴專欄鏈接:C++基于多設計模式下的同步&異步日志系統
📣歡迎各位大佬👍點贊🔥關注🚓收藏,🍉留言
主要內容實現了日志代碼設計的實用類設計,日志等級設計,日志消息類設計。
文章目錄
- C++基于多設計模式下的同步&異步日志系統day2
- 1.日志系統框架設計
- 1.1模塊劃分
- 1.2模塊關系圖
- 2.代碼設計
- 2.1實用類設計
- 2.2日志等級類設計
- 2.3日志消息類的設計
C++基于多設計模式下的同步&異步日志系統day2
1.日志系統框架設計
本項?實現的是?個多?志器?志系統,主要實現的功能是讓程序員能夠輕松的將程序運??志信息落地到指定的位置,且?持同步與異步兩種?式的?志落地?式。項?的框架設計將項?分為以下?個模塊來實現。
1.1模塊劃分
-
?志等級模塊:對輸出?志的等級進?劃分,以便于控制?志的輸出,并提供等級枚舉轉字符串功能。
- OFF:關閉
- DEBUG:調試,調試時的關鍵信息輸出
- INFO:提示,普通的提示性日志信息
- WARN:警告,不影響運行,但是需要注意一下的日志
- ERROR:錯誤,程序運行出現錯誤的日志
- FATAL:致命,一般是代碼異常導致程序無法繼續推進的運行的日志
-
日志消息模塊:中間存儲日志輸出所需的個各項要素信息
- 時間:描述本條日志的輸出時間
- 線程ID:描述本條日志是哪個線程輸出的
- 日志等級:描述本條日志的等級
- 日志數據:本條日志的有效載荷數據
- 日志文件名:描述本條日志在哪個源碼文件中輸出的
- 日志行號:描述本條日志在源碼文件的哪一行輸出的
-
?志消息格式化模塊:設置?志輸出格式,并提供對?志消息進?格式化功能
- 系統的默認?志輸出格式:%d{%H:%M:%S}%T[%t]%T[%p]%T[%c]%T%f:%l%T%m%n
- ->13:26:32 [2343223321] [FATAL] [root] main.c:76套接字創建失敗\n
- %d{%H:%M:%S}:表??期時間,花括號中的內容表??期時間的格式
- %T:表?制表符縮進
- %t:表?線程ID
- %p:表??志級別
- %c:表??志器名稱,不同的開發組可以創建??的?志器進??志輸出,?組之間互不影響
- %f:表??志輸出時的源代碼?件名
- %l:表??志輸出時的源代碼?號
- %m:表?給與的?志有效載荷數據
- %n:表?換?
- 設計思想:設計不同的?類,不同的?類從?志消息中取出不同的數據進?處理
-
?志消息落地模塊:決定了?志的落地?向,可以是標準輸出,也可以是?志?件,也可以滾動?
件輸出…- 標準輸出:表?將?志進?標準輸出的打印
- ?志?件輸出:表?將?志寫?指定的?件末尾
- 滾動?件輸出:當前以?件??進?控制,當?個?志?件??達到指定??,則切換下?個?件進?輸出
- 后期,也可以擴展遠程?志輸出,創建客?端,將?志消息發送給遠程的?志分析服務器
- 設計思想:設計不同的?類,不同的?類控制不同的?志落地?向
-
?志器模塊:
- 此模塊是對以上?個模塊的整合模塊,??通過?志器進??志的輸出,有效降低??的使?難度
- 包含有:?志消息落地模塊對象,?志消息格式化模塊對象,?志輸出等級
-
?志器管理模塊:
- 為了降低項?開發的?志耦合,不同的項?組可以有??的?志器來控制輸出格式以及落地?向,因此本項?是?個多?志器的?志系統
- 管理模塊就是對創建的所有?志器進?統?管理。并提供?個默認?志器提供標準輸出的?志輸出
-
異步線程模塊:
- 實現對?志的異步輸出功能,??只需要將輸出?志任務放?任務池,異步線程負責?志的落地輸出功能,以此提供更加?效的?阻塞?志輸出
1.2模塊關系圖
2.代碼設計
2.1實用類設計
提前完成?些零碎的功能接?,以便于項?中會?到
- 獲取系統時間
- 判斷?件是否存在
- 獲取?件的所在?錄路徑
- 創建?錄
/*實用工具類的實現:1.獲取系統時間2.判斷文件是否存在3.獲取文件所在路徑4.創建目錄
*/#include<iostream>
#include<ctime>
#include<unistd.h>
#include<sys/stat.h>namespace xupt
{namespace util{class Date{public:static size_t GetTime(){return (size_t)time(nullptr);} };class File{public:static bool exist(const std::string &pathname){//確保平臺移植性,我們不是用這個接口//return (access(pathname.c_str(), F_OK) == 0); //F_OK,文件存在且權限允許,返回0,struct st;if(stat(pathname.c_str(), &st) < 0){return false;}return true;}static std::string path(const std::string &pathname){size_t pos = pathname.find_last_of("/\\"); /*從路徑字符串的后面開始尋找第一個/或者\ */if(pos == std::string.npos) return "."; //如果沒有找到,那么證明這個文件就在當前的目錄return pathname.substr(0, pos + 1); //輸出包含最后一個/的位置的字符串}static void CreateDirectory(const std::string &pathname){size_t pos = 0, idx = 0;while(idx < pathname.size()){pos = pathname.find_first_of("/\\"); //尋找第一個/或者\if(pos == std::string.npos){mkdir(pathname, 0777); //如果沒有分隔符,那么就直接創建,并且設置權限為0777}std::string parent_dir = pathname.substr(0, idx + pos + 1); //截取包含從開始到/的父目錄if(exist(parent_dir) == true) { idx = pos + 1; continue; } //如果當前的目錄存在了,那么就跳過去找下一個mkdir(parent_dir, 0777);idx = pos + 1;}}};}
}
2.2日志等級類設計
①日志等級總共分為7個等級,分別為:
- UNKNOW表示未知錯誤
- DRBUG進?debug時候打印?志的等級
- INFO打印?些??提?信息
- WARN打印警告信息
- ERROR打印錯誤信息
- FATAL打印致命信息-導致程序崩潰的信息
- OFF關閉所有日志輸出
每一個項目中都會設置一個默認的日志輸出等級,只有輸出的日志等級大于等于默認限制等級的時候才可以進行輸出
②提供一個接口,將對應等級的枚舉,轉換為一個對應的字符串。
/*1.定義枚舉類,枚舉出日志等級2.提供轉換接口:將枚舉轉換為對應字符串
*/
#ifndef __M_LEVEL_H__
#define __M_LEVEL_H__namespace xupt
{class LogLevel{public:enum class value{UNKOWN = 0,DEBUG,INFO,WARN,ERROR,FATAL,OFF};static const char* toString(LogLevel::value level){switch (level){case LogLevel::value::DEBUG: return "DEBUG";case LogLevel::value::INFO: return "INFO";case LogLevel::value::WARN: return "WARN";case LogLevel::value::ERROR: return "ERROR";case LogLevel::value::FATAL: return "FATAL";case LogLevel::value::OFF: return "OFF";}return "UNKOWN";}};
}#endif
2.3日志消息類的設計
?志消息類主要是封裝?條完整的?志消息所需的內容,其中包括?志等級、對應的loggername、打
印?志源?件的位置信息(包括?件名和?號)、線程ID、時間戳信息、具體的?志信息等內容
定義日志消息類,進行日志中間信息的存儲:1.日志的輸出時間 用于過濾日志輸出時間2.日志等級 用于進行日志過濾分析3.源文件名稱 4.源代碼行號 用于定位出現錯誤的代碼位置5.線程ID 用于過濾出錯的線程6.日志主體消息7.日志器名稱 (當前支持多日志器的同時使用)
*/
#ifndef __M_MESSAGE_H__
#define __M_MESSAGE_H__#include"util.hpp"
#include"level.hpp"
#include<iostream>
#include<string>
#include<thread>namespace xupt
{struct LogMsg{size_t _ctime; //日志產生的時間LogLevel::value _level; //日志等級size_t _line; //行號std::thread::id _tid; //線程idstd::string _file; //文件名std::string _logger; //日志器名稱std::string _payload; //有效消息處理//對應的構造函數LogMsg(LogLevel::value level,size_t line,std::string file,std::string logger,std::string msg):_ctime(util::Date::now()),_level(level),_line(line),_tid(std::this_thread::get_id()),_file(file),_logger(logger),_payload(msg){}};}#endif
到這本篇博客的內容就到此結束了。
如果覺得本篇博客內容對你有所幫助的話,可以點贊,收藏,順便關注一下!
如果文章內容有錯誤,歡迎在評論區指正