C++ Log日志系统
阅读原文时间:2023年07月08日阅读:5

闲得无聊,瞎写的一个东西。

好多地方能够优化甚至可能重写,也没写,就记下了个思路在这里。

主要熟练一下C++17的内容。

version = 0.1

lc_log .h

1 #pragma once
2 #include
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
3 #include
4 #include
5 #include
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
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
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
42 void __getmsg(std::stringstream& ss, T&& value)
43 {
44 ss << value; 45 } 46 47 template
48 void __getmsg(std::stringstream& ss, T&& value, Ts&& … args)
49 {
50 ss << value; 51 __getmsg(ss, std::forward(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
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 _mLogs;
111
112 #if LOG_IS_NEED_LOCK
113 std::mutex _mx;
114 #endif
115 //std::future _thRun;
116 };
117
118
119 template
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 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
3 #include
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 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
2 #include
3
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
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
27 void getmsg(std::stringstream& ss, T&& value)
28 {
29 ss << value; 30 } 31 32 template
33 void getmsg(std::stringstream& ss, T&& value, Ts&& … args)
34 {
35 ss << value; 36 getmsg(ss, std::forward(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(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(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 }

我发现我越来越懒,咋办。。。