Qt的简易日志库实现及封装

Posted 特立独行的猫a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt的简易日志库实现及封装相关的知识,希望对你有一定的参考价值。

用于QT的一个简易日志功能模块封装。算不上强大和多高的性能,但是足够简单小巧。用于记录日志到文件够用了。单独的一个文件模块,使用时直接引入源码。想要其他功能,直接改代码即可。

C++的下的日志库有很多,如log4cpp、Easylogging++,eplog,g3log,Qt下也有log4qt。

还有简单小巧的QsLog,它是一个基于Qt的轻量级开源日志库。

QsLog的git地址:https://github.com/victronenergy/QsLog

log4qt的git地址:https://github.com/devbean/log4qt

如果这些都不想用,还想更简单小巧的,可以看以下这个简易模块封装。

查看日志推荐用baretailpro工具。

 使用方法

使用时只需工程文件.pro中包含模块源码即可。 

include(Logger/MessageLogger.pri)

MessageLogger.pri文件内容:

HEADERS  += $$PWD/MessageLogger.h
SOURCES += $$PWD/MessageLogger.cpp

INCLUDEPATH += $$PWD

简易封装 

#ifndef MESSAGELOGGER_H
#define MESSAGELOGGER_H

/** @description 用于Qt项目的一个简单的日志库,将日志存入日志文件(文本文件)中。
 *   典型用法示例:
 *   第一个 FileLogger 将日志输出到 stderr 上。
 *   第二个 FileLogger 将日志输出到文件。
 *   建议将这段代码放到 main 函数的开头处,但是要在 QCoreApplication 或 QApplication 之后。
 *     LoggerController logger;
 *     logger.attach(new FileLogger("stderr",
 *                               FileLogger::E_DEBUG |
 *                               FileLogger::E_INFO |
 *                               FileLogger::E_WARNING |
 *                               FileLogger::E_CRITICAL |
 *                               FileLogger::E_FATAL));
 *  logger.attach(new FileLogger("d:/log2.txt"));
 *  logger.startLogging();
*/

#include <QtCore/QString>
#include <QtCore/QFile>
#include <QtCore/QList>
#include <QtCore/QMap>
#include <QtCore/QDebug>
#include <QtCore/QMessageLogContext>

class FileLogger

public:
    enum LEVELE_DEBUG = 1, E_INFO = 2, E_WARNING = 4, E_CRITICAL = 8, E_FATAL = 16;
    FileLogger(QString name, LEVEL level);
    FileLogger(QString name = "stderr", bool debug=false, bool info=true, bool warning=true, bool critical=true, bool fatal=true);
    virtual ~FileLogger();
    /**
     * @brief setFileName 设置日志存储的文件名
     * @param name 日志存储的文件名,如果为 "stderr" 则输出到 stderr
     * @return
     */
    bool setFileName(QString name = "stderr");
    /**
     * @brief setLogLevel 设置哪些级别的信息要输出到文件
     * @param level 可以为 E_DEBUG、E_INFO、E_WARNING、E_CRITICAL、E_FATAL 或者这些项的组合(bit or)
     *              没有设置的 level 则不输出日志
     */
    void setLogLevel(LEVEL level);
    /**
     * @brief setLogLevel 设置哪些级别的信息要输出到文件
     * @param debug  true 表示 qDebug 信息输出到日志
     * @param info   true 表示 qInfo 信息输出到日志
     * @param warning  true 表示 qWarning 信息输出到日志
     * @param critical true 表示 qCritical 信息输出到日志
     * @param fatal    true 表示 qFatal 信息输出到日志
     */
    void setLogLevel(bool debug = false, bool info = true, bool warning = true, bool critical= true, bool fatal = true);
    virtual void writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg);
private:
    QString messageType(QtMsgType type);
    FileLogger(FileLogger &f) Q_UNUSED(f); // 不能被拷贝
    FileLogger& operator=( FileLogger &f) Q_UNUSED(f); // 不能被拷贝
private:
    QFile m_file;
    QMap<QtMsgType, bool> m_level;
    bool m_where;
;

class LoggerController

public:
    LoggerController()
    ~LoggerController();
    /**
     * @brief startLogging 启动日志系统,在这之后所有的调试信息发送到对应的 FileLogger
     */
    void startLogging();
    /**
     * @brief attach 在日志系统中注册一个新的 FileLogger
     * @param m_currentLogger
     */
    void attach(FileLogger *m_currentLogger);
    void detach(FileLogger *m_currentLogger);
private:
    static void writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg);
    static LoggerController * m_currentLogger;
    QList<FileLogger *> m_list;
;

#endif // MESSAGELOGGER_H
#include "MessageLogger.h"
#include <QtCore/QDateTime>
#include <QtCore/QTextStream>

FileLogger::FileLogger(QString name, bool debug, bool info, bool warning, bool critical, bool fatal)
    :m_where(true)

    setFileName(name);
    setLogLevel(debug, info, warning, critical, fatal);


FileLogger::FileLogger(QString name, LEVEL level)
:m_where(false)

    setFileName(name);
    setLogLevel(level);


FileLogger::~FileLogger()

    m_file.close();


bool FileLogger::setFileName(QString name)

    m_file.close();
    if(name == "stderr")
    
        return m_file.open(stderr, QIODevice::WriteOnly);
    
    else
    
        m_file.setFileName(name);
        return m_file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
    


void FileLogger::setLogLevel(LEVEL level)

    m_level[QtDebugMsg] = static_cast<bool> (level & E_DEBUG);
    m_level[QtInfoMsg] = static_cast<bool> (level & E_INFO);
    m_level[QtWarningMsg] = static_cast<bool> (level & E_WARNING);
    m_level[QtCriticalMsg] = static_cast<bool> (level & E_CRITICAL);
    m_level[QtFatalMsg] = static_cast<bool> (level & E_FATAL);


void FileLogger::setLogLevel(bool debug, bool info, bool warning, bool critical, bool fatal)

    m_level[QtDebugMsg] = debug;
    m_level[QtInfoMsg] = info;
    m_level[QtWarningMsg] = warning;
    m_level[QtCriticalMsg] = critical;
    m_level[QtFatalMsg] = fatal;


void FileLogger::writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg)

    if(!m_level[type])
    
        return;
    
    QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    QTextStream logfile(&m_file);

    logfile << strTime << ", ";
    logfile << messageType(type) << ", ";
    logfile << msg;
    if(context.file && m_where)
    
        logfile <<  ", (" << context.file << ":" << context.line << ", " << context.function << ")\\n";
    
    else
    
        logfile << endl;
    

    if(type == QtFatalMsg)
    
        abort();
    


QString FileLogger::messageType(QtMsgType type)

    QString str;
    switch (type)
    
    case QtDebugMsg:
        str = "[D]";
        break;
    case QtInfoMsg:
        str = "[I]";
        break;
    case QtWarningMsg:
        str = "[W]";
        break;
    case QtCriticalMsg:
        str = "[C]";
        break;
    case QtFatalMsg:
        str = "[F]";
    
    return str;


void LoggerController::attach(FileLogger *logger)

    m_list.append(logger);


void LoggerController::detach(FileLogger *logger)

    if(logger)
    
        m_list.removeOne(logger);
        delete logger;
    


void LoggerController::startLogging()

    m_currentLogger = this;
    qInstallMessageHandler(LoggerController::writeLog);


LoggerController::~LoggerController()

    qDeleteAll(m_list);

LoggerController* LoggerController::m_currentLogger = nullptr;

void LoggerController::writeLog(QtMsgType type, const QMessageLogContext &context, const QString &msg)

    if( m_currentLogger )
    
        QList<FileLogger *> &list = m_currentLogger->m_list;

        QList<FileLogger *>::const_iterator i;
        for (i = list.cbegin(); i != list.cend(); ++i)
        
            (*i)->writeLog(type, context, msg);
        
    


简单使用

#include "mainwindow.h"

#include <QApplication>

#include <QSettings>
#include <QString>
#include <QFileInfo>
#include <QTime>
#include <QDir>
#include "cglobal.h"
#include "MessageLogger.h"
#include "utils.h"

int main(int argc, char *argv[])

     //自适应高分辨率(DPI),不确定是否管用
     #if (QT_VERSION >= QT_VERSION_CHECK(5,9,0))
         QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
         QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
     #endif
    QApplication a(argc, argv);
    a.setFont(QFont("Microsoft Yahei", 9));//设置应用程序字体
    a.setWindowIcon(QIcon(":/main.ico"));//设置应用程序图标

    mkDirIfNotExist();

    //打印日志到文件中
    LoggerController logger;
    logger.attach(new FileLogger("stderr",
                               FileLogger::E_DEBUG,
                               FileLogger::E_INFO ,
                               FileLogger::E_WARNING ,
                               FileLogger::E_CRITICAL,
                               FileLogger::E_FATAL));
    QString dateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd_hhmmss");
    QString logName = LOG_PATH+dateTime+"_log.txt";
    //日志文件输入以下级别的日志
    FileLogger::LEVEL level =  (FileLogger::LEVEL)(FileLogger::E_INFO | FileLogger::E_WARNING);
    FileLogger *lg = new FileLogger(logName,level);
    logger.attach(lg);
    logger.startLogging();
    qInfo("程序启动...");
    qInfo(APP_VERION);


    MainWindow w;
    w.show();
    return a.exec();


void mkDirIfNotExist()
    QDir *folder = new QDir;
    bool exist,ok = false;
    exist = folder->exists(LOG_PATH);
    if(!exist)
        ok = folder->mkdir(LOG_PATH);
        if(!ok)
            qDebug("Error,创建日志文件夹失败");
        
    
    exist = folder->exists(PIC_PATH);
    if(!exist)
        ok = folder->mkdir(PIC_PATH);
        if(!ok)
            qDebug("Error,创建图片文件夹失败");
        
    

引用

QT 轻量级的LOG日志库_Duffy_Gallagher的博客-CSDN博客_qt日志库

Qt轻量级日志库QsLog的使用_百里杨的博客-CSDN博客_qt 日志库

以上是关于Qt的简易日志库实现及封装的主要内容,如果未能解决你的问题,请参考以下文章

python日志打印和写入并发简易版本实现

[ Linux ] 缓冲区的理解 以及简易模拟实现封装C标准库

linux下qt制作的界面怎么封装

Qt之zip压缩/解压缩(QuaZIP)

Qt自定义控件之日志控件

VC调用QT封装的动态库,求详解