QT保存日志到文件中以及捕捉崩溃日志

发布于:2025-07-09 ⋅ 阅读:(20) ⋅ 点赞:(0)

一、qInstallMessageHandler

QtMessageHandler qInstallMessageHandler(QtMessageHandler handler)

qInstallMessageHandler 是 Qt 框架中用于自定义消息处理的核心函数,主要用于拦截和重定向 Qt 应用程序的日志输出(如 qDebug()qWarning() 等)。

作用机制‌:

替换 Qt 默认的消息处理器,允许开发者自定义日志输出方式(如写入文件、发送到网络等)。传入的 handler 需匹配 void(QtMsgType, const QMessageLogContext&, const QString&) 函数签名‌。

参数说明‌:

1.handler: 自定义处理函数指针,若传入 nullptr 则恢复默认处理器‌。

2.返回值:指向前一个处理器的指针,便于链式调用或恢复‌。

二、QtMessageHandler handler

void(QtMsgType, const QMessageLogContext&, const QString&) 

这是一个Qt框架中用于自定义消息处理的函数签名类型,主要用于qInstallMessageHandler注册自定义日志处理器。

参数说明:

1.QtMsgType‌

Qt定义的枚举类型,标识消息级别,包括:

QtDebugMsg:调试信息(qDebug触发)
QtInfoMsg:普通信息(qInfo触发)
QtWarningMsg:警告信息(qWarning触发)
QtCriticalMsg:严重错误(qCritical触发)
QtFatalMsg:致命错误(qFatal触发)

2. QMessageLogContext‌

包含日志上下文信息的结构体,成员包括:

file:源代码文件名
line:代码行号
function:函数名
category:日志分类(Qt5.5+支持)

3. ‌QString&‌

实际日志内容的引用,需注意线程安全处理。

三、利用glog捕捉崩溃日志

google::InstallFailureWriter(&SignalHandler);

google::InstallFailureWriter(&SignalHandler) 是 Google Glog 日志库提供的核心函数,用于注册程序崩溃时的自定义信号处理器。

功能说明

当程序触发致命错误(如 SIGSEGVSIGABRT)时,自动调用绑定的 SignalHandler 函数,将崩溃信息写入日志文件或控制台。

参数要求

SignalHandler 函数签名‌

需匹配 void(const char* data, size_t size) 格式:

data:崩溃信息的字符指针
size:信息长度

四、代码示例

 log_test.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

QMAKE_LFLAGS += -no-pie

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

INCLUDEPATH += /usr/include/glog
LIBS += /usr/lib/x86_64-linux-gnu/libglog.so

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_debug_clicked();

    void on_pushButton_warn_clicked();

    void on_pushButton_crash_clicked();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_debug_clicked()
{
    qDebug()<<"这是一条调试信息日志。";
}

void MainWindow::on_pushButton_warn_clicked()
{
    qWarning()<<"这是一条警告信息日志。";
}

void MainWindow::on_pushButton_crash_clicked()
{
    QVector<int> vec;
    qDebug()<<"第一个数据为:"<<vec.at(0);
}

main.cpp

#include "mainwindow.h"

#include <QApplication>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QMutex>
#include <fstream>
#include "logging.h"
#include "log_severity.h"

QtMessageHandler gDefaultHandler = nullptr;
static QMutex logMutex;
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
    QMutexLocker locker(&logMutex);
    QDateTime time = QDateTime::currentDateTime();
    QString strTime = time.toString("MM-dd hh:mm:ss");
    QString strMessage = QString("[%1] [%2:%3] %4").arg(strTime).arg(QString(context.file).split("/").last()).arg(context.line).arg(msg);

    QString content;
    switch(type)
    {
        //调试信息提示
        case QtDebugMsg:
            content = QString("[调试信息] %1").arg(strMessage);
            break;
        //一般的warning提示
        case QtWarningMsg:
            content = QString("[警告信息] %1").arg(strMessage);
            break;
        //严重错误提示
        case QtCriticalMsg:
            content = QString("[严重错误] %1").arg(strMessage);
            break;
        //致命错误提示
        case QtFatalMsg:
            content = QString("[致命错误] %1").arg(strMessage);
            abort();
        default:
            break;
    }

    QString strPath = QCoreApplication::applicationDirPath() + "/log/";
    QFile runLog(strPath + "log.txt");

    runLog.open(QIODevice::WriteOnly | QIODevice::Append);
    if(runLog.size() >= 1024 * 5000)
    {
        runLog.close();
        QString backupName = QString("log_%1.txt").arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss"));
        QFile::copy(strPath + "log.txt", strPath + backupName);
        runLog.remove();

        QFile outFile3(strPath + "log.txt");
        outFile3.open(QIODevice::WriteOnly | QIODevice::Append);
        QTextStream ts(&outFile3);
        ts << content << endl;
    }
    else
    {
        QTextStream ts(&runLog);
        ts << content << endl;
    }
    //
    if(gDefaultHandler)
    {
        gDefaultHandler(type, context, msg);
    }
}


// 扑捉到程序崩溃或者中断时,把相应的信息打印到log文件和输出到屏幕。
void SignalHandler(const char* data, int size) {

    QString logPath = QCoreApplication::applicationDirPath() + "/log/crash/" ;

   //组织文件名称
    QString strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    logPath = logPath + strTime + ".log";
    std::string glog_file = logPath.toStdString();

    //创建文件
    std::ofstream fs(glog_file, std::ios::app);

    //打印到文件
    std::string str = std::string(data, size);
    if (fs.is_open()) {
        fs.write(data, size);
    }
    fs.close();
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString path = QCoreApplication::applicationDirPath() + "/log";
    QString logPath = path + "/crash";
    QDir dir(logPath);
    if(!dir.exists())
        if(dir.mkpath(logPath))
            qDebug()<<"创建路径:"<<logPath;

    gDefaultHandler = qInstallMessageHandler(messageHandler);

    google::InitGoogleLogging(argv[0]);//使用glog之前必须先初始化库,仅需执行一次,括号内为程序名
    google::InstallFailureSignalHandler();
    google::InstallFailureWriter(&SignalHandler);

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

mainwindow.ui

 运行结果

日志生成

 


网站公告

今日签到

点亮在社区的每一天
去签到