简单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)...);
}

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

相关推荐
meiying883811 小时前
快递单号批量查询Python脚本:从手动到自动化的完整实现
开发语言·python·自动化
@大迁世界12 小时前
告别 Go,拥抱 Rust
开发语言·golang·rust
SEO_juper12 小时前
Node.js 重定向链检测工具:301 跳了几跳、有没有成环,一次看清
xml·开发语言·python·node.js·json·bash
学逆向的12 小时前
C 指针常量与常量指针
c语言·开发语言·网络安全
低调滴开发13 小时前
3 行代码写崩一个函数?切片才是 Rust 字符串处理的正确姿势
开发语言·后端·rust
CodeYp201913 小时前
第15讲:二叉搜索树
开发语言·c++·二叉搜索树
猫猫.15313 小时前
HashTable、HashMap、ConcurrentHashMap 核心区别总结
java·开发语言·java-ee
乌暮14 小时前
综合案例:宠物电商系统
java·开发语言·spring·mvc·restful·1024程序员节
大文说跨境14 小时前
亚马逊多店铺的图片素材怎么批量去重:EXIF 与哈希的处理流程
开发语言·php
大风起兮云飞扬丶16 小时前
Java——枚举
java·开发语言