前言
因为我有很多服务是跑在后台的,每次查看日志都很麻烦需要ssh 到服务后台去查看,如果日志每次UDP通过打过来,同时也可以远程控制它的输出模式,那该多好啊。
日志库需求
1.最基本的控制台、文件和UDP输出,因为是qt程序用,所以要兼容qDebug输出
2.使用方便,简单,易用。
3.如果同时支持配置文件或者直接调用日志文件接口来初始化日志
4.尽量使用c++标准函数
流程图
最终实现
发送Demo
控制显示Demo
使用方法
- 初始化日志库
1.1. 通过直接调用函数接口的方式实现
#define E_DEMO_THREAD_ID 0x22
#define E_DEMO_THREAD_STR "DemoThread"
//初始化日志文件
CLogSystemMgr::Instance()->InitLogSystem("LogSystemDemo1", E_LOG_SYSTEM_TYPE_PRINTF | E_LOG_SYSTEM_TYPE_FILE| E_LOG_SYSTEM_TYPE_UDP);
//设置日志文件策略
CLogSystemMgr::Instance()->SetFileLogStrategy(E_FILE_LOG_SYSTEM_MODE_FOLDER, "LogSystemDemo1",QString(a.applicationDirPath() +"/../Log/" ).toLocal8Bit().data(), 1, 1);
//设置UDP发送日志 建议不开启 ,建议使用exe远程进行控制
CLogSystemMgr::Instance()->SetLogSystemUDP(true,"10.10.10.213",22333);
//设置是或否可以使用远程控制日志 为了安全,可以无需开启
CLogSystemMgr::Instance()->EnableControlMonitorUDP(true, "127.0.0.1", 22334);
//设置QDebug重定向到日志库 使用默认输出模块
CLogSystemMgr::Instance()->SetLogSystemRedirectQDebug(true);
//注册一个自定义模块
if (!CLogSystemMgr::Instance()->RegisterLogModule(E_DEMO_THREAD_ID, E_DEMO_THREAD_STR))
{
std::string strError;
CLogSystemMgr::Instance()->GetErrorInfo(strError);
MY_Error() << strError;
}
//设置单个模块的打印级别开关
CLogSystemMgr::Instance()->EnableLogModuleLevel(E_DEMO_THREAD_ID, E_LOG_SYSTEM_LEVEL_DEBUG, true);
CLogSystemMgr::Instance()->EnableLogModuleLevel(E_DEMO_THREAD_ID, E_LOG_SYSTEM_LEVEL_INFO, true);
//设置单个模块的输出策略
CLogSystemMgr::Instance()->EnableLogModuleShowInfo(E_DEMO_THREAD_ID, E_LOG_SYSTEM_SHOW_INFO_DATE| E_LOG_SYSTEM_SHOW_INFO_TIME| E_LOG_SYSTEM_SHOW_INFO_MILLISECOND| E_LOG_SYSTEM_SHOW_INFO_LOG_LEVEL| E_LOG_SYSTEM_SHOW_INFO_LOG_MODULE_ID| E_LOG_SYSTEM_SHOW_INFO_LOG_MODULE_NAME| E_LOG_SYSTEM_SHOW_INFO_DEBUG_INFO,true);
//设置所有模块的输出策略
CLogSystemMgr::Instance()->EnableLogModuleShowInfo(E_LOG_SYSTEM_SHOW_INFO_DEBUG_INFO,true);
1.2. 通过序列换XML来初始化日志库
//传入配置文件地址 也可以使用上面那种直接调用函数的做法,看你实际情况使用
std::string strError;
std::string strPath = "./../Config/LogSystemConfig.xml";
if (!InitLogMgr(strError,strPath))
{
qCritical() << strError.c_str();
}
配置文件
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<LogSystem LogAppName="Adsdp" Printf="true" File="true" Console="false" UDP="false" serialDevice="false">
<重定向QT输出>true</重定向QT输出>
<远程控制 IP="127.0.0.1" port="22334">true</远程控制>
<UDP输出 IP="10.10.10.170" port="22347"/>
<串口输出 SerialName="/dev/ttyS0" SerialPort="9600"/>
<!--文件输出介绍> name文件名称,LogAppName dir输出路径 空=pwd/../Log OutMode输出策略 建议使用策略1
0 = 不对日志进行分割(长时间写入可能会导致文件越写越大)
1 = 按照时间分割 OutMode = 1后面两个配置有效 MaxFile最大文件量 MaxSize单个文件大小MB <文件输出介绍-->
<文件输出 FileName="Adsdp" dir="./../Log" OutMode="1" MaxFile="5" MaxSize="20"/>
<!--日志模式说明>库会自动创建全局打印模块 name Global ID 0xffffffff 请注意LogModelName和LogModelID是唯一的不可重复的 <日志模式说明-->
<日志模式 LogModelName="Global" LogModelID="0xffffffff">
<输出格式 年月日="true" 时分秒="false" 毫秒="true" 日志级别="true" 模块ID="true" 模块名="false" 调试信息="false"/>
<输出等级 MSG="true" Debug="false" Info="true" Warn="true" Error="true" Dump="false"/>
</日志模式>
<日志模式 LogModelName="Demo1" LogModelID="0x22">
<输出格式 年月日="true" 时分秒="false" 毫秒="true" 日志级别="true" 模块ID="true" 模块名="false" 调试信息="false"/>
<输出等级 MSG="true" Debug="false" Info="true" Warn="true" Error="true" Dump="false"/>
</日志模式>
</LogSystem>
</root>
- 使用方法
//自定义打印宏,打印到全局模块
MY_Debug() << "默认模块没有开启 debug输入,所以这句话打不进去";
MY_MSG() << "但是我可以使用MSG 打印,我还可以使用double" << 2.225;
MY_MSG() <<QStringLiteral("Qstring 也可以 而且我还可以打16进制 0x")<<QByteArray("4132").toHex().data();
MY_Error() << QStringLiteral("就问你气不气!");
//打印到指定模块
LogOutDebug(E_DEMO_THREAD_ID)<< "E_DEMO_THREAD_ID 模块开启了 debug输入,所以这句话可以打进去";
MY_Error_C(E_DEMO_THREAD_ID) << "所以这句话可以打进去";
LogOutDebug(std::string("DemoThread")) << "当然我使用模块的名称也是可以打进去的";
//使用qt的QDebug输出
qWarning() << QStringLiteral("这是用qdebug 默认模块输出的日志");
static int ccc = 222333;
qWarning() << ccc;
下载地址
测试程序下载地址
测试程序下载地址:https://download.csdn.net/download/luck_anan/85436103
源码下载地址
CSDN:
GitHub:
GitLab:
缺陷
因为要兼容Qt 所以这个库不是纯c++库 ,并且使用了qt的 容器队列 XML解析与QDateTime。
最后
本人才疏学浅,还有很多不足,欢迎各位指出,也请收下留情,勿喷。
转载请注明出处谢谢。