色偷偷91综合久久噜噜-色偷偷成人-色偷偷尼玛图亚洲综合-色偷偷人人澡久久天天-国内精品视频一区-国内精品视频一区二区三区

Hello! 歡迎來到小浪云!


【Linux】日志設計模式與實現


avatar
小浪云 2025-04-17 18

1. 什么是設計模式

??it行業這么火, 涌入的人很多. 俗話說林子大了啥鳥都有. 大佬和菜雞們兩極分化的越來越嚴重. 為了讓菜雞們不太拖大佬的后腿, 于是大佬們針對?些經典的常見的場景, 給定了?些對應的解決?案, 這個就是設計模式。 ??在it行業中,設計模式(design patterns) 是一套被廣泛認可的、用于解決軟件設計中常見問題的最佳實踐。它們提供了一種標準化的方法來處理特定的設計問題,并且可以幫助開發人員編寫更清晰、更具可維護性的代碼。

2. 日志認識

??計算機中的日志是記錄系統和軟件運行中發生事件的文件,主要作用是監控運行狀態、記錄異常信息,幫助快速定位問題并?持程序員進?問題修復。它是系統維護、故障排查和安全管理的重要工具。 日志格式以下幾個指標是必須得有的:

時間戳日志等級日志內容

以下幾個指標是可選的:

文件名行號進程,線程相關id信息等 日志有現成的解決方案,如:spdlog、glog、Boost.Log、Log4cxx等等,我們依舊采用自定義日志的方式。這里我們采用設計模式-策略模式來進行日志的設計,我們想要的日志格式如下:代碼語言:JavaScript代碼運行次數:0運行復制

[可讀性很好的時間] [?志等級] [進程pid] [打印對應?志的?件名][?號] - 消息內容,?持可變參數[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [16] - hello world[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [17] - hello world[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [18] - hello world[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [20] - hello world[2024-08-04 12:27:03] [DEBUG] [202938] [main.cc] [21] - hello world[2024-08-04 12:27:03] [WARNING] [202938] [main.cc] [23] - hello world

3. 日志實現首先我們需要設置日志等級:代碼語言:javascript代碼運行次數:0運行復制

// ?志等級    enum class LogLevel    {        DEBUG,        INFO,        WARNING,        ERROR,        FATAL    };    // ?志轉換成為字符串    std::string LogLevelToString(LogLevel level)    {        switch (level)        {        case LogLevel::DEBUG:            return "DEBUG";        case LogLevel::INFO:            return "INFO";        case LogLevel::WARNING:            return "WARNING";        case LogLevel::ERROR:            return "ERROR";        case LogLevel::FATAL:            return "FATAL";        default:            return "UNKNOWN";        }    }

設置日志時間代碼語言:javascript代碼運行次數:0運行復制

    // 根據時間戳,獲取可讀性較強的時間信息    std::string GetCurrTime()    {        time_t tm = time(nullptr);        struct tm curr;        localtime_r(&tm, &curr);        char timebuffer[64];        snprintf(timebuffer, sizeof(timebuffer), "%4d-%02d-%02d %02d:%02d:%02d ",                 curr.tm_year + 1900,//這是因為這里的年份比實際年份少1900                 curr.tm_mon+1,//這是因為月份是在0~11                 curr.tm_mday,                 curr.tm_hour,                 curr.tm_min,                 curr.tm_sec);        return timebuffer;    }

日志策略模式:

??有了準備工作后,我們在開始設計日志類之前還需要確定日志的策略模式——也就是日志是往控制臺上輸出還是文件中輸出。

代碼語言:javascript代碼運行次數:0運行復制

// 策略模式,策略接?    class LogStrategy    {    public:        virtual ~LogStrategy() = default;                     // 策略的析構函數        virtual void SyncLog(const std::string &message) = 0; // 不同模式核?是刷新?式的不同    };

控制臺日志策略:代碼語言:javascript代碼運行次數:0運行復制

// 控制臺?志策略,就是?志只向顯?器打印,?便我們debug    class ConsoleLogStrategy : public LogStrategy    {    public:        void SyncLog(const std::string &amp;message) override        {            LockGuard LockGuard(_mutex);            std::cerr 文件日志策略:代碼語言:javascript<i class="icon-code"></i>代碼運行次數:<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>運行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>復制<pre class="prism-token token line-numbers javascript">    class FileLogStrategy : public LogStrategy    {    public:        // 構造函數,建?出來指定的?錄結構和?件結構        FileLogStrategy(const std::string logpath = defaultpath, std::string logfilename = defaultname)            : _logpath(logpath), _logfilename(logfilename)        {            LockGuard lockguard(_mutex);            if (std::filesystem::exists(_logpath))                return;            try            {                std::filesystem::create_directories(_logpath);            }            catch (const std::filesystem::filesystem_error &amp;e)            {                std::cerr 具體日志類:<p>我們先確定日志策略模式,默認是控制臺輸出;然后定義一個內部類用來確定日志輸出的信息:</p>代碼語言:javascript<i class="icon-code"></i>代碼運行次數:<!-- -->0<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewbox="0 0 16 16" fill="none"><path d="M6.66666 10.9999L10.6667 7.99992L6.66666 4.99992V10.9999ZM7.99999 1.33325C4.31999 1.33325 1.33333 4.31992 1.33333 7.99992C1.33333 11.6799 4.31999 14.6666 7.99999 14.6666C11.68 14.6666 14.6667 11.6799 14.6667 7.99992C14.6667 4.31992 11.68 1.33325 7.99999 1.33325ZM7.99999 13.3333C5.05999 13.3333 2.66666 10.9399 2.66666 7.99992C2.66666 5.05992 5.05999 2.66659 7.99999 2.66659C10.94 2.66659 13.3333 5.05992 13.3333 7.99992C13.3333 10.9399 10.94 13.3333 7.99999 13.3333Z" fill="currentcolor"></path></svg>運行<svg width="16" height="16" viewbox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 15.5V3.5H14.5V15.5H4.5ZM12.5 5.5H6.5V13.5H12.5V5.5ZM9.5 2.5H3.5V12.5H1.5V0.5H11.5V2.5H9.5Z" fill="currentcolor"></path></svg>復制<pre class="prism-token token line-numbers javascript"> // 具體的?志類    class Logger    {    public:        Logger()        {            // 默認使?顯?器策略,如果???次指明了策略,會釋放在申請,測試的時候注意析構次數            UseConsoleStrategy();        }        ~Logger()        {        }        void UseConsoleStrategy()        {            _strategy = std::make_unique<consolelogstrategy>();        }        void UseFileStrategy()        {            _strategy = std::make_unique<filelogstrategy>();        }        class LogMessage        {        public:            LogMessage(LogLevel type, std::string filename, int line, Logger &amp;logger)                : _curr_time(GetCurrTime()),                  _pid(getpid()),                  _filename(filename),                  _line(line),                  _logger(logger)            {                // stringstream不允許拷?,所以這?就當做格式化功能使?                std::stringstream ssbuffer;                ssbuffer             LogMessage &amp;operatorSyncLog(_loginfo);                }            }        private:            LogLevel _type;         // ?志等級            std::string _curr_time; // ?志時間            pid_t _pid;             // 寫??志的進程ID            std::string _filename;  // 對應的?件名            int _line;              // 對應的?件?號            Logger &amp;_logger;        // 引?外部logger類, ?便使?策略進?刷新            std::string _loginfo;   // ?條合并完成的,完整的?志信息        };        LogMessage operator()(LogLevel type, std::string filename, int line)        {            return LogMessage(type, filename, line, *this);        }    private:        std::unique_ptr<logstrategy> _strategy;    };</logstrategy></filelogstrategy></consolelogstrategy>

最后將上述內容放在一個命名空間LogModule內部,并定義一個日志類對象:代碼語言:javascript代碼運行次數:0運行復制

#include #include #include #include #include #include #include  // C++17, 需要?版本編譯器和-std=c++17#include #include "Mutex.hpp"namespace LogModule{    using namespace MutexModule;    // 默認路徑和?志名稱    const std::string defaultpath = "./log/";    const std::string defaultname = "log.txt";    // ?志等級    enum class LogLevel    {        DEBUG,        INFO,        WARNING,        ERROR,        FATAL    };    // ?志轉換成為字符串    std::string LogLevelToString(LogLevel level)    {        switch (level)        {        case LogLevel::DEBUG:            return "DEBUG";        case LogLevel::INFO:            return "INFO";        case LogLevel::WARNING:            return "WARNING";        case LogLevel::ERROR:            return "ERROR";        case LogLevel::FATAL:            return "FATAL";        default:            return "UNKNOWN";        }    }    // 根據時間戳,獲取可讀性較強的時間信息    std::string GetCurrTime()    {        time_t tm = time(nullptr);        struct tm curr;        localtime_r(&tm, &curr);        char timebuffer[64];        snprintf(timebuffer, sizeof(timebuffer), "%4d-%02d-%02d %02d:%02d:%02d ",                 curr.tm_year + 1900,                 curr.tm_mon+1,                 curr.tm_mday,                 curr.tm_hour,                 curr.tm_min,                 curr.tm_sec);        return timebuffer;    }    // 策略模式,策略接?    class LogStrategy    {    public:        virtual ~LogStrategy() = default;                     // 策略的構造函數        virtual void SyncLog(const std::string &message) = 0; // 不同模式核?是刷新?式的不同    };    // 控制臺?志策略,就是?志只向顯?器打印,?便我們debug    class ConsoleLogStrategy : public LogStrategy    {    public:        void SyncLog(const std::string &message) override        {            LockGuard LockGuard(_mutex);            std::cerr ();        }        void UseFileStrategy()        {            _strategy = std::make_unique();        }        class LogMessage        {        public:            LogMessage(LogLevel type, std::string filename, int line, Logger &logger)                : _curr_time(GetCurrTime()),                  _pid(getpid()),                  _filename(filename),                  _line(line),                  _logger(logger)            {                // stringstream不允許拷?,所以這?就當做格式化功能使?                std::stringstream ssbuffer;                ssbuffer             LogMessage &operatorSyncLog(_loginfo);                }            }        private:            LogLevel _type;         // ?志等級            std::string _curr_time; // ?志時間            pid_t _pid;             // 寫??志的進程ID            std::string _filename;  // 對應的?件名            int _line;              // 對應的?件?號            Logger &_logger;        // 引?外部logger類, ?便使?策略進?刷新            std::string _loginfo;   // ?條合并完成的,完整的?志信息        };        LogMessage operator()(LogLevel type, std::string filename, int line)        {            return LogMessage(type, filename, line, *this);        }    private:        std::unique_ptr _strategy;    };    //定義日志類對象    Logger logger;    // 使?宏,可以進?代碼插?,?便隨時獲取?件名和?號    #define LOG(type) logger(type, __FILE__, __LINE__)    // 提供選擇使?何種?志策略的?法    #define ENABLE_CONSOLE_LOG_STRATEGY() logger.UseConsoleStrategy()    #define ENABLE_FILE_LOG_STRATEGY() logger.UseFileStrategy()}

測試代碼:代碼語言:javascript代碼運行次數:0運行復制

#include <iostream>#include "Log.hpp"using namespace LogModule;void fun(){    int a = 10;    LOG(LogLevel::FATAL) <p>結果如下:</p> <figure class=""><img src="https://img.php.cn/upload/article/001/503/042/174487142432849.jpg" alt="【Linux】日志設計模式與實現"></figure>4. 結語<p>??日志可以幫助我們快速準確的了解程序運行的狀況,出現的錯誤以及相關內容;同時日志的設計模式如解耦也值得我們學習。</p></iostream>

相關閱讀

主站蜘蛛池模板: 天天干天天玩 | 日日爽天天干 | 91久久精品日日躁夜夜躁欧美 | 久久久久久亚洲精品影院 | 七月婷婷丁香 | 国产精品美女久久久久 | 中文字幕国产日韩 | 色涩播 | a一级毛片视频免费看 | 婷婷色狠狠干 | 99久久国产综合精品swag超清 | 天天干女人 | 伊人小视频 | 毛片美女 | 按摩毛片| 噜噜噜色 | 奇米色婷婷 | 国模gogo大尺度亚洲 | 日本xxxxxxx69xx| 小明成人免费永久性看看 | 亚洲国产成人99精品激情在线 | 玖玖精品 | 在线看一区二区 | 后进极品白嫩翘臀在线视频 | 国产亚洲精品国产 | 综合 91在线精品 | 极品美女久久久久久久久久久 | 天天干天天操天天插 | 成年人网站在线观看免费 | 一级女人 | 狠狠色噜噜狠狠米奇777 | 久久99精品一久久久久久 | 欧美成人久久久免费播放 | 日本福利一区二区 | 夜夜躁日日躁狠狠久久 | 色综合久久天天综线观看 | 欧美色99| 国内精品久久久久久影院网站小说 | 97久久精品人人做人人爽 | 一级做视频c视频播放 | 思思91精品国产综合在线 |