一、源码
logoutput.h
#ifndef LOGOUTPUT_H
#define LOGOUTPUT_H
#include <QObject>
#include <spdlog/spdlog.h>
// 全局 spdlog logger
extern std::shared_ptr<spdlog::logger> qspdLogger;
// 用法1:接管qt的打印信息
class logOutput : public QObject
{
Q_OBJECT
public:
static logOutput *Instance();
explicit logOutput(QObject *parent = 0);
~logOutput();
public:
void start(); // 安装日志钩子
void stop(); // 卸载日志钩子
private:
static QScopedPointer<logOutput> m_self;
bool m_isRun;
QString m_filename; // 文件名
int m_maxSize; // 文件最大大小 单位kb
};
//用法2:封装宏,方便直接使用spdlog
#define LOG_TRACE(format,...) qspdLogger->trace(std::string("[{}:{}]")+format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_DEBUG(format,...) qspdLogger->debug(std::string("[{}:{}]")+format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_INFO(format,...) qspdLogger->info(std::string("[{}:{}]")+format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_WARN(format,...) qspdLogger->warn(std::string("[{}:{}]")+format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_ERROR(format,...) qspdLogger->error(std::string("[{}:{}]")+format,__FILE__,__LINE__,##__VA_ARGS__);
#define LOG_FATAL(format,...) qspdLogger->critical(std::string("[{}:{}]")+format,__FILE__,__LINE__,##__VA_ARGS__);
#endif // LOGOUTPUT_H
logoutput.cpp
#include "logoutput.h"
#include <QMutex>
#include <spdlog/sinks/rotating_file_sink.h>
// 全局 spdlog logger
std::shared_ptr<spdlog::logger> qspdLogger;
// 自定义消息处理函数
void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context)
// 将 QString 转换为 UTF-8 编码的 std::string
QByteArray byteArray = msg.toUtf8();
std::string utf8Msg(byteArray.constData(), byteArray.size());
switch (type) {
case QtDebugMsg:
qspdLogger->debug(utf8Msg);
break;
case QtInfoMsg:
qspdLogger->info(utf8Msg);
break;
case QtWarningMsg:
qspdLogger->warn(utf8Msg);
break;
case QtCriticalMsg:
qspdLogger->critical(utf8Msg);
break;
case QtFatalMsg:
qspdLogger->critical(utf8Msg);
abort();
}
}
QScopedPointer<logOutput> logOutput::m_self;
logOutput *logOutput::Instance()
{
if (m_self.isNull()) {
static QMutex mutex;
QMutexLocker locker(&mutex);
if (m_self.isNull()) {
m_self.reset(new logOutput);
}
}
return m_self.data();
}
logOutput::logOutput(QObject *parent) : QObject(parent)
{
m_isRun = false;
}
logOutput::~logOutput()
{
}
//安装钩子
void logOutput::start()
{
if (m_isRun)
return;
m_isRun = true;
// 初始化 spdlog,日志文件:/log/server.log,大小:10MB,保留数量:20
qspdLogger = spdlog::rotating_logger_mt("file_logger", "log/log.txt", 10*1024*1024, 20);
spdlog::set_level(spdlog::level::debug);
spdlog::flush_on(spdlog::level::debug);
spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e [%l] %v");
qInstallMessageHandler(outputMessage);
}
//卸载钩子
void logOutput::stop()
{
if (!m_isRun)
return;
m_isRun = false;
qInstallMessageHandler(0);
}
二、使用方法
1.在main中,或者自己的初始化函数中增加如下语句:
logOutput::Instance()->start();
2.有2种打印方式
方式1:使用QT自带的打印语句,如qDebug、qInfo等
QString a = "test";
int b;
qDebug() << "test" << a << b;
方式2:使用LOG宏定义语句
std::string a;
int b;
LOG_ERROR("a:{},b:{}", a, b);
3.如果spdlog用了我的扩展版(扩展spdlog1.15.0,适配QString和msvc2015-优快云博客),宏定义也可支持QString的输出
std::string a;
int b;
QString qstr;
LOG_ERROR("a:{},b:{},QString:{}", a, b, qstr);