C++ Log日志系統


閑得無聊,瞎寫的一個東西。

好多地方能夠優化甚至可能重寫,也沒寫,就記下了個思路在這里。

主要熟練一下C++17的內容。

version = 0.1

 

lc_log .h

 1 #pragma once
 2 #include <stdio.h>
 3 
 4 namespace LC
 5 {
 6 namespace LC_LOG
 7 {
 8 class Log final
 9 {
10 public:
11     Log(const Log&) = delete;
12     Log& operator=(const Log&) = delete;
13 
14     Log(const char* szPath = nullptr);
15     ~Log();
16 
17 private:
18     bool    __Open(const char* szPath);
19     int     __Close();
20     bool    __Write(const char* szTime, const char* szFile, const char* szLine, const char* szType, const char* szMsg);
21     //int     __Lock(bool isLock);
22 
23 private:
24     friend class LogMgr;
25     friend class LogFileInfo;
26     FILE* _pFile = nullptr;
27 };
28 
29 };
30 };

 

 

lc_log.cpp

 1 #include "lc_log.h"
 2 #include <sys/fcntl.h>
 3 #include <unistd.h>
 4 #include <stdlib.h>
 5 #include <sstream>
 6 
 7 namespace LC
 8 {
 9 namespace LC_LOG
10 {
11     Log::Log(const char* szPath)
12     {
13         if(szPath == nullptr)
14             return;
15         
16         __Close();
17         __Open(szPath);
18     }
19 
20     Log::~Log()
21     {
22         __Close();
23     }
24 
25     bool Log::__Open(const char* szPath)
26     {
27         if(szPath == nullptr)
28             return false;
29 
30         #ifdef WIN32
31             fopen_s(&_pFile, szPath, "at+");
32         #else
33             _pFile = fopen(szPath, "at+");
34         #endif
35 
36         return _pFile == nullptr;     
37     }
38 
39     bool Log::__Write(const char* szTime, const char* szFile, const char* szLine, const char* szType, const char* szMsg)
40     {
41         if(_pFile == nullptr)
42             return false;
43         
44         std::stringstream szlog;
45         szlog \
46             << "[" << szType \
47             << "] time: " << szTime \
48             << "  file: " << szFile \
49             << "  line: " << szLine \
50             << "   " << szMsg \
51             << std::endl;
52         
53         //__Lock(true);
54         int res = fputs(szlog.str().c_str(), _pFile);
55         //__Lock(false);
56 
57         return res >= 0;
58     }
59 
60     // int Log::__Lock(bool isLock)
61     // {
62     //     #ifdef _LINUX
63     //         return lockf(fileno(_pFile), isLock ? F_LOCK : F_ULOCK, 0);
64     //     #else   //windows
65     //         //TOOD:
66     //         //
67     //         return 0;
68     //     #endif
69     // }
70 
71     int Log::__Close()
72     {
73         if(!_pFile) return 0;
74         return fclose(_pFile);        
75     }
76 };
77 };

 

lc_logmgr.h

  1 #pragma once
  2 #include "lc_log.h"
  3 #include <unordered_map>
  4 #include <time.h>
  5 #include <filesystem>
  6 #include <sstream>
  7 #include <string>
  8 #include <future>
  9 #include <condition_variable>
 10 
 11 namespace LC
 12 {
 13 namespace LC_LOG
 14 {
 15 #define LOG_INFO        "INFO"
 16 #define LOG_WARNING     "WARNING"
 17 #define LOG_CHECKIT     "CHECKIT"
 18 #define LOG_ERROR       "ERROR"
 19 #define LOG_FATAL       "FATAL"
 20 
 21 #define LOGFILE_MAX_SIZE        (10 * 1024 * 1024)
 22 #define LOGNAME_MAX_LENGTH      128
 23 #define LOGNAME_PREFIX          "Log"
 24 #define LOGNAME_SUFFIX          ".log"
 25 #define LOG_IS_NEED_LOCK        true
 26 
 27 // #ifdef _WIN32
 28 //     #define SEP "\\"
 29 // #else
 30     #define SEP "/"
 31 //#endif
 32 
 33 #define LOGID uint64_t
 34 
 35 #define __STR_LC(s) #s   
 36 #define _STR_LC(s)  __STR_LC(s)
 37 
 38 //@format "%Y-%m-%d %H:%M:%S"
 39 extern void __str_time(char* out, const char* format = "%Y-%m-%d");
 40 
 41 template<typename T>
 42 void __getmsg(std::stringstream& ss, T&& value)
 43 {
 44     ss << value;
 45 }
 46 
 47 template<typename T, typename ... Ts>
 48 void __getmsg(std::stringstream& ss, T&& value, Ts&& ... args)
 49 {
 50     ss << value;
 51     __getmsg(ss, std::forward<Ts>(args) ...);
 52 }
 53 
 54 struct __LogMsgBase
 55 {
 56     std::string _file;
 57     std::string _line;
 58     std::string _time;
 59 
 60     __LogMsgBase& instance()
 61     {
 62         static __LogMsgBase ins;
 63         return ins;
 64     }
 65 };
 66 
 67 struct LogFileInfo
 68 {
 69     LogFileInfo()
 70         : _num(0)
 71         , _pLog(nullptr)
 72     {
 73     }
 74 
 75     ~LogFileInfo();
 76 
 77     std::string     _title;
 78     std::string     _basePath;
 79     int             _num;
 80 
 81     std::string     _name;
 82     Log*            _pLog;
 83 
 84     void GetPath(std::string& out) const;
 85     void InitName();
 86     void ReOpen();
 87     static void BaseName(const std::string& title, std::string& out);
 88 };
 89 
 90 class LogMgr final
 91 {
 92 private:
 93     LogMgr();
 94 
 95 public:
 96     ~LogMgr();
 97 
 98     static LogMgr& Instance()
 99     {
100         static LogMgr ins;
101         return ins;
102     }
103 
104     bool Register(LOGID id, const char* path, const char* title);
105 
106     template<typename ... TArgs>
107     bool WriteLog(LOGID id, const char* type, const char* time, const char* file, const char* line, TArgs&& ... args);
108 
109 private:
110     std::unordered_map<LOGID, LogFileInfo* > _mLogs;
111 
112 #if LOG_IS_NEED_LOCK
113     std::mutex _mx;    
114 #endif                              
115     //std::future<bool> _thRun;
116 };
117     
118 
119 template<typename ... TArgs>
120 bool LogMgr::WriteLog(LOGID id, const char* type, const char* time, const char* file, const char* line, TArgs&& ... args)
121 {
122 #if LOG_IS_NEED_LOCK
123     std::unique_lock<std::mutex> ul(_mx);
124 #endif
125 
126     auto it = _mLogs.find(id);
127     if(it == _mLogs.end())
128         return false;
129 
130     LogFileInfo* pInfo = it->second;
131     Log* pLog = pInfo->_pLog;
132     if(nullptr == pLog)
133         return false;
134 
135     std::string fullPath;
136     pInfo->GetPath(fullPath);
137 
138     while(std::filesystem::exists(fullPath.c_str()) 
139         && std::filesystem::file_size(fullPath.c_str()) >= LOGFILE_MAX_SIZE)
140     {
141         pInfo->_num++;
142         pInfo->InitName();
143         pInfo->GetPath(fullPath);
144         pInfo->ReOpen();
145     }
146 
147     std::stringstream ss;
148     __getmsg(ss, args...);
149 
150     return pLog->__Write(time, file, line, type, ss.str().c_str());
151 }
152 
153 #define RegisterLogger(id, path, title) LC::LC_LOG::LogMgr::Instance().Register(id, path, title)
154 
155 #define LogWriteBase(id, type, msg...) \
156     do{ \
157         char timestr[64];    \
158         LC::LC_LOG::__str_time(timestr, "%Y-%m-%d %H:%M:%S");  \
159         LC::LC_LOG::LogMgr::Instance().WriteLog(id, type, timestr, __FILE__, _STR_LC(__LINE__), msg);    \
160     }while(0)
161 };
162 };

 

lc_logmgr.cpp

  1 #include "lc_logmgr.h"
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 
  5 namespace LC
  6 {
  7 namespace LC_LOG
  8 {
  9     void __str_time(char* out, const char* format)
 10     {
 11         if(out == nullptr)
 12             return;
 13 
 14         time_t t = time(NULL);
 15         strftime(out, 64, format, localtime(&t));
 16     }
 17 
 18     LogFileInfo::~LogFileInfo()
 19     {
 20         delete _pLog;
 21     }
 22 
 23     void LogFileInfo::GetPath(std::string& out) const
 24     {
 25         out.clear();
 26 
 27         out += _basePath;
 28         const char& last = _basePath.back();
 29         if(!(last == '/' || last == '\\'))
 30             out.append(SEP);
 31 
 32         out.append(_name);
 33     }
 34 
 35     void LogFileInfo::InitName()
 36     {
 37         BaseName(_title, _name);
 38         if(_num > 0)
 39             _name.append("_").append(std::to_string(_num));
 40         
 41         _name.append(LOGNAME_SUFFIX);
 42     }
 43 
 44     void LogFileInfo::ReOpen()
 45     {
 46         if(_pLog == nullptr)
 47             return;
 48 
 49         std::string fullpath;
 50         GetPath(fullpath);
 51         _pLog->__Close();
 52         _pLog->__Open(fullpath.c_str());
 53     }
 54 
 55     void LogFileInfo::BaseName(const std::string& title, std::string& out)
 56     {
 57         out.clear();
 58 
 59         char strtime[64];
 60         __str_time(strtime);
 61         out
 62             .append(LOGNAME_PREFIX)
 63             .append("_")
 64             .append(title)
 65             .append("_")
 66             .append(strtime);
 67     }
 68 
 69     LogMgr::LogMgr()
 70     {
 71         // _thRun = std::async(std::launch::deferred, 
 72         //     []() -> bool
 73         //     {
 74                 
 75         //     }, 
 76         // );
 77     }
 78 
 79     LogMgr::~LogMgr()
 80     {
 81         for (auto& pairEach : _mLogs)
 82         {
 83             LogFileInfo* pInfo = pairEach.second;
 84             delete pInfo;
 85         }
 86         _mLogs.clear();
 87     }
 88 
 89     bool LogMgr::Register(LOGID id, const char* path, const char* title)
 90     {
 91     #if LOG_IS_NEED_LOCK
 92         std::unique_lock<std::mutex> ul(_mx);
 93     #endif
 94 
 95         if(_mLogs.find(id) != _mLogs.end())
 96             return true;
 97 
 98         LogFileInfo* pInfo = new LogFileInfo();
 99         if(pInfo == nullptr)
100             return false;
101 
102         pInfo->_basePath = path;
103         pInfo->_title = title;
104         {
105             pInfo->InitName();
106 
107             std::string fullPath;
108             pInfo->GetPath(fullPath);
109 
110             if(!(std::filesystem::exists(fullPath.c_str()) 
111                 && std::filesystem::file_size(fullPath.c_str()) >= LOGFILE_MAX_SIZE))
112             {
113                 pInfo->_pLog = new Log(fullPath.c_str());
114                 if(pInfo->_pLog == nullptr)
115                 {
116                     delete pInfo;
117                     return false;
118                 }
119                 _mLogs.insert(std::make_pair(id, pInfo));
120                 return true;
121             }
122         }
123 
124         int num = 1;
125         do
126         {
127             pInfo->_num = num;
128             pInfo->InitName();
129 
130             std::string fullPath;
131             pInfo->GetPath(fullPath);
132             if(std::filesystem::exists(fullPath.c_str()) 
133                 && std::filesystem::file_size(fullPath.c_str()) >= LOGFILE_MAX_SIZE)
134             {
135                 ++num; continue;
136             }
137 
138             pInfo->_pLog = new Log(fullPath.c_str());
139             if(pInfo->_pLog == nullptr)
140             {
141                 //delete pInfo;
142                 return false;
143             }
144             _mLogs.insert(std::make_pair(id, pInfo));
145             return true;
146         } while (num < 10000);
147 
148         return false;
149     }
150 };
151 };

 

 

main.cpp

 1 #include <iostream>
 2 #include <vector>
 3 
 4 #include <time.h>
 5 #include <string>
 6 #include <thread>
 7 #include <future>
 8 #include <sstream>
 9 #include <chrono> 
10 #include "lc_logmgr.h"
11 
12 #define C_SS(s) # s
13 #define _GETMSG(ss, args...) getmsg(ss, args)
14 
15 #define __STR_LC(s) #s   
16 #define _STR_LC(s)  __STR_LC(s)
17 
18 struct item
19 {
20     void show(const std::string& s)
21     {
22         std::cout << s << std::endl;
23     }
24 };
25 
26 template<typename T>
27 void getmsg(std::stringstream& ss, T&& value)
28 {
29     ss << value;
30 }
31 
32 template<typename T, typename ... Ts>
33 void getmsg(std::stringstream& ss, T&& value, Ts&& ... args)
34 {
35     ss << value;
36     getmsg(ss, std::forward<Ts>(args) ...); 
37     return;
38 }
39 
40 using namespace std::chrono;
41 int main()
42 {
43     item t;
44     std::string sss = "qwe";
45     RegisterLogger(0x01, "./", "TEST");
46 
47     std::thread th1([](){
48         for (size_t i = 0; i < 100000; i++)
49         {
50            LogWriteBase(0x01, LOG_INFO, "a ", i, " ", 2 * i + 3);
51         }
52         std::cout << "log a over. " << std::endl;
53     });
54 
55     std::thread th2([](){
56         for (size_t i = 0; i < 100000; i++)
57         {
58            LogWriteBase(0x01, LOG_INFO, "b ", i, " ", 2 * i + 3);
59         }
60         std::cout << "log b over. " << std::endl;
61     });
62 
63     std::thread th3([](){
64         for (size_t i = 0; i < 100000; i++)
65         {
66            LogWriteBase(0x01, LOG_INFO, "c ", i, " ", 2 * i + 3);
67         }
68         std::cout << "log c over. " << std::endl;
69     });
70 
71     th1.join();
72     th2.join();
73     th3.join();
74 
75     // auto time_now = system_clock::now();
76     // auto duration_in_ms = duration_cast<milliseconds>(time_now.time_since_epoch());
77     // uint64_t nFactTime = duration_in_ms.count();
78     // for (size_t i = 0; i < 100000; i++)
79     // {
80     //    LogWriteBase(0x01, LOG_INFO, "qwe", i, " ", 2 * i + 3);
81     // }
82     
83     // auto time_now2 = system_clock::now();
84     // auto duration_in_ms2 = duration_cast<milliseconds>(time_now2.time_since_epoch());
85     // uint64_t nFactTime2 = duration_in_ms2.count();
86     // std::cout << nFactTime2 - nFactTime << std::endl;
87 
88     std::cout << "-----over-----" << std::endl;
89     return 0;
90 }

 

 

我發現我越來越懶,咋辦。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM