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 }
我发现我越来越懒,咋办。。。
C++ Log日志系统的更多相关文章
- MySQL日志系统:redo log与binlog
日志系统主要有redo log(重做日志)和binlog(归档日志).redo log是InnoDB存储引擎层的日志,binlog是MySQL Server层记录的日志, 两者都是记录了某些操作的日志 ...
- Linux**系统实现log日志自动清理
Linux系统实现log日志自动清理 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- LOG收集系统(一):原日志至收集
Date: 20140207Auth: Jin 设置一个LOG收集系统1. 收集原生(不解析,不压缩)的业务日志和WEB日志(NGINX,PHP)2. 提供给开发,测试直接阅读和下载 需求分析原生日志 ...
- 成功配置TOMCAT的LOG4J日志系统,格式:HTML+每天以YYYY-MM-DD.LOG命名的日志文件
关于log4j.properties文件在web项目中放的位置,找过很多,最后实践结果是: 一.web项目 二.放在src的目录里面,然后项目生成后会自动在\WEB-INF\classes文件里有份l ...
- Linux系统的LOG日志文件及入侵后日志的清除
UNIX网管员主要是靠系统的LOG,来获得入侵的痕迹.当然也有第三方工具记录入侵系统的 痕迹,UNIX系统存放LOG文件,普通位置如下: /usr/adm - 早期版本的UNIX/var/adm - ...
- MySQL 日志系统之 redo log 和 binlog
之前我们了解了一条查询语句的执行流程,并介绍了执行过程中涉及的处理模块.一条查询语句的执行过程一般是经过连接器.分析器.优化器.执行器等功能模块,最后到达存储引擎. 那么,一条 SQL 更新语句的执行 ...
- MySQL日志系统bin log、redo log和undo log
MySQL日志系统bin log.redo log和undo log 今人不见古时月,今月曾经照古人. 简介:日志是MySQL数据库的重要组成部分,记录着数据库运行期间各种状态信息,主要包括错误日 ...
- C++ 高性能无锁日志系统
服务器编程中,日志系统需要满足几个条件 .高效,日志系统不应占用太多资源 .简洁,为了一个简单的日志功能引入大量第三方代码未必值得 .线程安全,服务器中各个线程都能同时写出日志 .轮替,服务器不出故障 ...
- Atitit.log日志技术的最佳实践attilax总结
Atitit.log日志技术的最佳实践attilax总结 1. 日志的意义与作用1 1.1. 日志系统是一种不可或缺的单元测试,跟踪调试工具1 2. 俩种实现[1]日志系统作为一种服务进程存在 [2] ...
随机推荐
- R绘图(3): 散点图添加文本注释
这里以火山图为例进行说明,在转录组分析中,火山图是很常见的一类图,纵轴表示p_value,横轴表示log (fold change).单一的散点图绘制很简单,火山图比较难处理的地方就是一些基因的注释, ...
- JavaScript数组的几个常用的API
一. 扁平化嵌套数组/展平和阵列孔--flat() 1.实现效果 var arr1 = [1, 2, [3, 4]]; arr1.flat(); // [1, 2, 3, 4] var arr2 = ...
- hessian简单介绍
Hessian是基于HTTP的轻量级远程服务解决方案,Hessian像Rmi一样,使用二进制消息进行客户端和服务器端交互.但与其他二进制远程调用技术(例如Rmi)不同的是,它的二进制消息可以移植其他非 ...
- python-给一个参数n,例如3:先输出1,2,3,4,5,6,7,8,9,每三个数后换行,后输出1,4,7,2,5,8,3,6,9
""" 2 定义一个函数,fn(n)其中n表示输入n行n列的矩阵,需要满足的要求是在n为 3时先输出 3 1 2 3 4 4 5 6 5 7 8 9 6 后输出 7 1 ...
- 史上超强拷贝仓——GitHub 热点速览 v.21.11
作者:HelloGitHub-小鱼干 Clone-Wars 是真的强,能细数 70+ 知名应用网站的源码,即便你不看代码,也可以了解下各大网站的所用技术栈.同样很强的是用 OpenCV 实现的图片转 ...
- 2021华为软件精英挑战赛(C/C++实现)-苦行僧的实现过程
下面给出2021华为软件精英挑战赛参与的整个过程,虽然成绩不是很好,但是也是花了一些时间的,希望后面多多学习,多多进步. 代码已经上传到了Github上:https://github.com/myFr ...
- badusb论述
"BadUSB"是2014年计算机安全领域的热门话题之一,该漏洞由Karsten Nohl和Jakob Lell共同发现 攻击原理 TEENSY 攻击者在定制攻击设备时,会向USB ...
- JDK8之后,在java语言这条路怎么走?
前言 自2017年9月以来,Oracle按照免费的开源许可证(类似于Linux的许可证)提供JDK版本 .从Java SE 11(2018年9月,LTS)开始,Oracle不仅为开源许可下的所有用户免 ...
- kafka-简介-01
1.kafka是什么? Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特 ...
- GO-01-GoLang的快捷键