简单Qt日志接口

cpp 复制代码
#ifndef LOGGER_H
#define LOGGER_H

#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QMutex>
#include <QQueue>
#include <QThread >

class Logger : public QObject {
    Q_OBJECT

public:
    static Logger* getInstance();
    void startLogging();
    void log(const QString& message, const QString& val, const char* file, int line);

private:
    explicit Logger(QObject *parent = nullptr);
    QFile logFile;
    QTextStream logStream;
    QMutex mutex;
    QQueue<QString> logQueue;
    bool logging;

    void processLogQueue();

    static Logger* instance;
};

class LoggerThread : public QThread {
public:
    void run() override {
        Logger::getInstance()->startLogging();
    }
};

#define LOG(message, val) Logger::getInstance()->log(message, val, __FILE__, __LINE__)

#endif // LOGGER_H
cpp 复制代码
#include "logger.h"
#include <QFileInfo>

Logger* Logger::instance = nullptr;

Logger::Logger(QObject *parent) : QObject(parent), logging(false) {
    logFile.setFileName("out.log");
}

Logger* Logger::getInstance() {
    if (instance == nullptr) {
        instance = new Logger();
    }
    return instance;
}

void Logger::startLogging() {
    if (logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
        logStream.setDevice(&logFile);
        logging = true;
        processLogQueue();
    } else {
        qCritical() << "Error opening log file.";
    }
}

void Logger::log(const QString& message, const QString& val, const char* file, int line) {
        QFileInfo fileInfo(file);
        QString msg = QString("[%1] [%2:%3] %4 %5")
                      .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz"))
                      .arg(fileInfo.fileName())
                      .arg(QString::number(line))
                      .arg(message)
                      .arg(val);

    {
        QMutexLocker locker(&mutex);
        logQueue.enqueue(msg);
    }

    if (logging) {
        processLogQueue();
    }
}

void Logger::processLogQueue() {
    while (!logQueue.isEmpty()) {
        logStream << logQueue.dequeue() << endl;
    }
}
cpp 复制代码
#include <QCoreApplication>
#include <QDebug>
#include "logger.h"

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    LoggerThread loggerThread;
    loggerThread.start();
    loggerThread.wait(); // 等待线程完成
    
    QString strVal = "test";
    LOG("This is a log message.", strVal );
    LOG("Another log message.", strVal );

    return app.exec();
}

进一步拓展,可以随机输入不确定的参数:

cpp 复制代码
#define LOG(...) Logger::getInstance()->log(__VA_ARGS__, __FILE__, __LINE__)

void Logger::log(const char* file, int line, const QString& message) {
    QFileInfo fileInfo(file);
    QString msg = QString("[%1] [%2:%3] [Thread ID: %4] %5")
                      .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz"))
                      .arg(fileInfo.fileName())
                      .arg(line)
                      .arg(QThread::currentThreadId())
                      .arg(message);

    {
        QMutexLocker locker(&mutex);
        logQueue.enqueue(msg);
    }

    if (logging) {
        processLogQueue();
    }
}

template<typename T, typename... Args>
void Logger::log(const char* file, int line, const QString& message, T&& value, Args&&... args) {
    QString newValue = QString::fromUtf8(QByteArray::number(value));
    log(file, line, message + " " + newValue, std::forward<Args>(args)...);
}

下一步还可以输入不同类型来确定打印,可以使用模板函数来处理等等;

相关推荐
杯莫停丶5 小时前
设计模式之:模板模式
开发语言·设计模式
开发者小天5 小时前
调整为 dart-sass 支持的语法,将深度选择器/deep/调整为::v-deep
开发语言·前端·javascript·vue.js·uni-app·sass·1024程序员节
老猿讲编程6 小时前
C++中的奇异递归模板模式CRTP
开发语言·c++
汤姆yu8 小时前
基于python的化妆品销售分析系统
开发语言·python·化妆品销售分析
ScilogyHunter8 小时前
C语言标准库完全指南
c语言·开发语言
sali-tec8 小时前
C# 基于halcon的视觉工作流-章52-生成标定板
开发语言·图像处理·人工智能·算法·计算机视觉
应茶茶8 小时前
C++11 核心新特性:从语法重构到工程化实践
java·开发语言·c++
程子的小段9 小时前
C 语言实例 - 字符串复制
c语言·开发语言
-森屿安年-9 小时前
STL 容器:stack
开发语言·c++
歪歪1009 小时前
C#如何在数据可视化工具中进行数据筛选?
开发语言·前端·信息可视化·前端框架·c#·visual studio