若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/89155318
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
Qt开发专栏:三方库开发技术(点击传送门)
前话
日志系统整理并模块化。
Log4Qt介绍
Log4Qt是使用Trolltech Qt Framework的Apache Software Foundation Log4j包的C ++端口。它旨在供开源和商业Qt项目使用。
Qt4版本的log4qt
源码下载
当前最新版本为log4qt-0.3.zIP,这源码包最后修改日期为2009年。
Sourceforge下载地址:https://sourceforge.net/projects/log4qt/
CSDN下载:https://download.csdn.net/download/qq21497936/11087843
模块化
源码加入日志模块:
解压到当前文件夹:
将log4qt的源码包含到模块中:
封装日志类
封装成独立的日志类,这样不论用什么日志系统只需要改变该类,代码其他模块无需改变,使用单例模式,因log4qt本身是线程安全的,所以不用考虑多线程,下面是封装的log4qt日志类。
Log.h
#ifndef LOG_H #define LOG_H #include <QObject> #include <QMutex> #include <QMutexLocker> #include <QCoreApplication> #include "log4qt/logger.h" #include "log4qt/basicconfigurator.h" /************************************************************\ * 类名:Log * 描述:封装log4qt开源库类 * 注意:模块已带log4qt for qt4 和 qt5两个版本; * 模块已带log4qt配置文件,分为4级别:DEBUG > INFO > WARN > ERROR * 信号: * 函数: * instance() - 获取日志唯一实例 * 槽函数: * slot_init() - 初始化加载配置文件 * slot_debug() - 调试级别日志 * slot_info() - 信息级别日志 * slot_warn() - 警告级别日志 * slot_error() - 错误级别日志 * * 作者:红模仿 * 联系方式:QQ21497936 * 博客地址:https://blog.csdn.net/qq21497936 * 日期 版本号 描述 * 2019年04月09日 v1.0.0 基础日志模块 \************************************************************/ class Log : public QObject { Q_OBJECT public: explicit Log(QObject *parent = nullptr); signals: public slots: static Log * instance(); public slots: void init(QString configFilePath); public slots: void debug(QString msg); void info(QString msg); void warn(QString msg); void error(QString msg); private: static Log *_pInstance; static QMutex _mutex; static Log4Qt::Logger * _pLoggerDebug; static Log4Qt::Logger * _pLoggerInfo; static Log4Qt::Logger * _pLoggerWarn; static Log4Qt::Logger * _pLoggerError; static QString _configFilePath; };
Log.cpp
#include "Log.h" #include "log4qt/log4qt.h" #include "log4qt/propertyconfigurator.h" Log * Log::_pInstance = 0; QMutex Log::_mutex; Log4Qt::Logger * Log::_pLoggerDebug = 0; Log4Qt::Logger * Log::_pLoggerInfo = 0; Log4Qt::Logger * Log::_pLoggerWarn = 0; Log4Qt::Logger * Log::_pLoggerError = 0; QString Log::_configFilePath; Log::Log(QObject *parent) : QObject(parent) { // 一定要配置文件,不然运行起来会直接当掉 Log4Qt::BasicConfigurator::configure(); } Log *Log::instance() { if(!_pInstance) { QMutexLocker mutexLocker(&_mutex); if(!_pInstance) { Log *pInstance = new Log(); _pInstance = pInstance; } } return _pInstance; } void Log::init(QString configFilePath) { _configFilePath = configFilePath; Log4Qt::PropertyConfigurator::configure(_configFilePath); _pLoggerDebug = Log4Qt::Logger::logger("debug"); _pLoggerInfo = Log4Qt::Logger::logger("info"); _pLoggerWarn = Log4Qt::Logger::logger("warn"); _pLoggerError = Log4Qt::Logger::logger("error"); } void Log::debug(QString msg) { _pLoggerDebug->debug(msg); } void Log::info(QString msg) { _pLoggerInfo->info(msg); } void Log::warn(QString msg) { _pLoggerWarn->warn(msg); } void Log::error(QString msg) { _pLoggerError->error(msg); }
测试代码
main.cpp
#include <QApplication> #include <QTextCodec> #include <QThread> #include "Log.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QThread::currentThread()->setObjectName("主线程"); QTextCodec *codec = QTextCodec::codecForName("utf-8"); QTextCodec::setCodecForLocale(codec); Log::instance()->init(QCoreApplication::applicationDirPath() + "/" +"etc/log.conf"); Log::instance()->debug("调试测试日志系统当中..."); Log::instance()->info("信息测试日志系统当中..."); Log::instance()->warn("警告测试日志系统当中..."); Log::instance()->error("错误测试日志系统当中..."); return a.exec(); }
配置文件
log.conf
log4j.logger.debug=CONSOLE,debug log4j.appender.debug=org.apache.log4j.RollingFileAppender log4j.appender.debug.Threshold=DEBUG log4j.appender.debug.appendFile=true log4j.appender.debug.Encoding=UTF-8 log4j.appender.debug.File=log/debug.txt log4j.appender.debug.MaxFileSize=4096KB log4j.appender.debug.MaxBackupIndex=7 log4j.appender.debug.layout=org.apache.log4j.PatternLayout log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.zzz}[%t][%p] %m%n log4j.logger.info=CONSOLE,info,debug log4j.appender.info=org.apache.log4j.RollingFileAppender log4j.appender.info.Threshold=DEBUG log4j.appender.info.appendFile=true log4j.appender.info.Encoding=UTF-8 log4j.appender.info.File=log/info.txt log4j.appender.info.MaxFileSize=4096KB log4j.appender.info.MaxBackupIndex=7 log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.zzz}[%t][%p] %m%n log4j.logger.warn=CONSOLE,info,debug,warn log4j.appender.warn=org.apache.log4j.RollingFileAppender log4j.appender.warn.Threshold=DEBUG log4j.appender.warn.appendFile=true log4j.appender.warn.Encoding=GBK log4j.appender.warn.File=log/warn.txt log4j.appender.warn.MaxFileSize=4096KB log4j.appender.warn.MaxBackupIndex=2 log4j.appender.warn.layout=org.apache.log4j.PatternLayout log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.zzz}[%t][%p] %m%n log4j.logger.error=CONSOLE,info,debug,warn,error log4j.appender.error=org.apache.log4j.RollingFileAppender log4j.appender.error.Threshold=DEBUG log4j.appender.error.appendFile=true log4j.appender.error.Encoding=UTF-8 log4j.appender.error.File=log/error.txt
协作开发
define.h
// 开发过程中暂时使用qDebug替代 1-使用debug打印输出 0-使用日志输出 #if 1 // 以文件行列记录信息,非以类名对象形式 #define LOG_DEBUG(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1:%2:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("DEBUG") \ .arg(msg); #define LOG_INFO(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1:%2:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("INFO") \ .arg(msg); #define LOG_WARN(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1:%2:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("WARN") \ .arg(msg); #define LOG_ERROR(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1:%2:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("ERROR") \ .arg(msg); // 以类名对象形式记录信息 #define LOG_OBJECT_DEBUG(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1::%2:%3").arg(this->metaObject()->className()).arg(__FUNCTION__).arg(__LINE__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("DEBUG") \ .arg(msg); #define LOG_OBJECT_INFO(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1::%2:%3").arg(this->metaObject()->className()).arg(__FUNCTION__).arg(__LINE__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("INFO") \ .arg(msg); #define LOG_OBJECT_WARN(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1::%2:%3").arg(this->metaObject()->className()).arg(__FUNCTION__).arg(__LINE__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("WARN") \ .arg(msg); #define LOG_OBJECT_ERROR(msg) qDebug() << QString("[%1][%2][%3][%4]%5") \ .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \ .arg(QString("%1::%2:%3").arg(this->metaObject()->className()).arg(__FUNCTION__).arg(__LINE__)) \ .arg(QThread::currentThread()->objectName()) \ .arg("ERROR") \ .arg(msg); // 写入日志系统 #else // 以文件行列记录信息,非以类名对象形式 #define LOG_DEBUG(msg) Log::instance()->debug(QString("[%1]%2").arg(QString("%1:%2:%3").arg(__FILE__).arg(__LINE__).arg(__FUNCTION__)).arg(msg)); #define LOG_INFO(msg) Log::instance()->info(msg); #define LOG_WARN(msg) Log::instance()->warn(msg); #define LOG_ERROR(msg) Log::instance()->error(msg); // 以类名对象形式记录信息 #define LOG_OBJECT_DEBUG(msg) Log::instance()->debug(QString("[%1]%2").arg(QString("%1::%2:%3").arg(this->metaObject()->className()).arg(__FUNCTION__).arg(__LINE__)).arg(msg)); #define LOG_OBJECT_INFO(msg) Log::instance()->info(msg); #define LOG_OBJECT_WARN(msg) Log::instance()->warn(msg); #define LOG_OBJECT_ERROR(msg) Log::instance()->error(msg); #endif
Qt4版本日志移植到qt5编译过程出现错误
错误一:识别QtMsgHandler类
“error: 'QtMsgHandler' does not name a type”
解决方法:QtMsgHandler替换为QtMessageHandler
Qt5做了一些更改:
更改如下图:
错误二:QObject类未声明
点击跳转到错误文件,添加QObject
错误三:QTextCodec编码错误
点击跳转到错误文件,修改log4qt源码:
错误四:操作符“<<”歧义
直接修改吧,改变下存储的数据类型:
错误五:qInstallMsgHandle未声明
宏修改如下:
成功运行,如下图:
Qt5版本的Log4Qt
下载后直接将qt4版本的pri文件换成qt5版本的,qt5版本的则没有以上的一些编译错误,替换模块,如下图:
源码下载
CSDN:https://download.csdn.net/download/qq21497936/11097306
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/89155318