Qt三方库开发技术:log4Qt介绍、编译和使用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Qt三方库开发技术:log4Qt介绍、编译和使用

若该文为原创文章,未经允许不得转载

原博主博客地址: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


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
5天前
|
C++
VS2019编译VTK-9.1.0+Qt5.15.2
本文介绍了在VS2019和Qt 5.15.2环境下编译VTK 9.1.0的过程,包括成功编译无警告和错误的截图、修改的pro文件内容,以及在QML中加入VTK的失败尝试和参考链接。
|
5天前
|
C语言 Android开发 C++
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
本文介绍了使用MTuner软件进行Qt MinGW编译程序的内存泄漏检测的方法,提供了MTuner的下载链接和测试代码示例,并通过将Debug程序拖入MTuner来定位内存泄漏问题。
基于MTuner软件进行qt的mingw编译程序的内存泄漏检测
|
4天前
|
C++
vtkdicom0.8_vtk9.2_dcmtk3.6.7_qt6.2编译OK
本文介绍了如何编译整合VTK 9.2、DICOM 0.8、DCMTK 3.6.7和Qt 6.2的步骤,包括安装Qt、CMake配置以及确认相关路径和版本设置。
vtkdicom0.8_vtk9.2_dcmtk3.6.7_qt6.2编译OK
|
4天前
|
Unix 网络虚拟化 C++
VS2022+Qt5.14.2成功编译MITK2022.10
使用VS2022和Qt5.14.2成功编译MITK2022.10的过程,包括编译结果的截图、遇到的编译问题的解决方法、两个重要的注意事项(patch文件格式的修改和ITK-gitclone-lastrun文件的存在),以及参考链接。文中详细描述了如何解决编译过程中遇到的错误C2220和警告C4819,以及如何修改文件编码和尾行格式。
VS2022+Qt5.14.2成功编译MITK2022.10
|
4天前
编译QCefView+VS2019+QT5.15.2
本文介绍了如何编译QCefView项目,并在VS2019和Qt 5.15.2环境下集成,包括编译结果、要点、cmake部署Qt的方法和相关参考链接。
编译QCefView+VS2019+QT5.15.2
|
5天前
|
人工智能
三战VS2019编译VTK7.1+Qt5.15.2
本文记录了作者在VS2019环境下编译VTK 7.1与Qt 5.15.2的历程,包括正确配置方法、遇到的编译错误以及解决过程。
|
5天前
|
人工智能 C++
初步编译QT5.15.2+VS2019+VTK8.2.0
本文介绍了在VS2019中编译QT 5.15.2和VTK 8.2.0的过程,包括编译结果、cmake库编译配置和cmake应用配置脚本,以及推荐的参考链接。
|
4天前
|
计算机视觉
vs2019_qt6.2.4_dcmtk3.6.7_vtk9.2.2_itk5.3_opencv4.6.0编译记录
这篇文章记录了使用VS2019编译Qt6.2.4、DCMTK3.6.7、VTK9.2.2、ITK5.3和OpenCV4.6.0的过程,包括下载和编译步骤,并提供了遇到编译错误时的解决方案和参考链接。
vs2019_qt6.2.4_dcmtk3.6.7_vtk9.2.2_itk5.3_opencv4.6.0编译记录
|
4天前
|
C语言 C++ Windows
QT多插件通信框架CTK编译记录
本文记录了编译QT多插件通信框架CTK的过程,包括编译结果截图、部署配置、Log4Qt编译配置、参考链接和拓展资料。文中提供了详细的编译步骤和配置文件示例,以及相关的资源链接。
QT多插件通信框架CTK编译记录
|
4天前
|
机器学习/深度学习 Java 计算机视觉
opencv4.5.5+qt5.15.2+vtk9.1+mingw81_64编译记录
本文记录了使用mingw81_64编译OpenCV 4.5.5、Qt 5.15.2、VTK 9.1的详细过程,包括编译结果截图、编译步骤、遇到的问题及其解决方案,以及相关参考链接。文中还提到了如何编译boost源码为静态库,并提供了测试代码示例。
opencv4.5.5+qt5.15.2+vtk9.1+mingw81_64编译记录
下一篇
无影云桌面