一、日志库选型
日志库现在有很多,c++中较为出名的有log4cxx、spdlog等,但qt中要是用的不是很复杂,可以采用qt自带的日志机制,方便且实用
二、qt日志机制实现
-
实现一个注册函数
void DemoLog::outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) -
注册
qInstallMessageHandler(outputMessage);//注册MsgHandler回调函数 -
注意要点
qt机制不难,但是要想项目中实际使用,还必须考虑到线程安全、日志堆积问题后台调用日志显示等 -
下面实现一个实际项目使用的日志类,示例如下:
DemoLog g_DemoLog;
DemoLog::DemoLog(QObject *parent)
:QObject(parent),
m_mutex(QMutex::Recursive),
m_backConsole(false)//用来控制是否在指定控制台界面输出日志信息
{
}
DemoLog::~DemoLog()
{
}
void DemoLog::initLog(const bool &bConsole, const QString &strFilePath)
{
qInstallMessageHandler(outputMessage);//注册MsgHandler回调函数
//多线程安全
QMutexLocker locker(&m_mutex);
m_bConsole = bConsole;
m_strFilePath = strFilePath;
QJsonObject jsonLog = CommonUtils::readJsonFromFile(QApplication::applicationDirPath() + "/config/configSystem.json");
m_bNeedLog = jsonLog.value("Skey_LogNeed").toBool(true);
m_nMaxCountLogFile = jsonLog.value("SKey_LogDate").toInt(30);
QString strLogPath = QApplication::applicationDirPath() + strFilePath;
deleteLogFile(strLogPath, m_nMaxCountLogFile);
//corefile clear
deleteLogFile("/corefile", m_nMaxCountCoreFile);
QDir dirLog(strLogPath);
if (!dirLog.exists())
{
dirLog.mkpath(strLogPath);
}
QDateTime noeDate = QDateTime::currentDateTime();
QString strBuf = QString("%1_0.log").arg(noeDate.toString("yyyyMMdd-hhmmss"));
m_strFileName = QString("%1/%2").arg(strLogPath).arg(strBuf);
m_strBaseFileName = m_strFileName;
}
void DemoLog::setBackConsole(const bool &bStatus)
{
m_backConsole.store(bStatus);
}
void DemoLog::outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
//真正的日志处理函数
g_DemoLog.processMsg(type, context, msg);
}
void DemoLog::processMsg(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context);
QMutexLocker locker(&m_mutex);
const qint64 M = 5 * 1024 *1024;
qint64 fileSize = QFileInfo(m_strFileName).size();
if (fileSize > M)
{
m_nLogNum++ ;
if (m_nLogNum == INT32_MAX)
{
m_nLogNum = 0;
}
m_strFileName = m_strBaseFileName.left(m_strBaseFileName.length() - 4) + QString::number(m_nLogNum) + ".log";
//clear log and corefile
QString strLogPath = QApplication::applicationDirPath() + m_strFilePath;
deleteLogFile(strLogPath, m_nMaxCountLogFile);
deleteLogFile("/corefile", m_nMaxCountCoreFile);
}
QDateTime nowDate = QDateTime::currentDateTime();
QString strMsgLog = QString("[%1] %2").arg(nowDate.toString("yyyy-MM-dd hh:mm:ss:zzz")).arg(msg);
strMsgLog.replace("\\n", "\n");
//for devloper
if (m_bConsole && type != QtDebugMsg)
{
QString strConsole = QString("%1 %2\n").arg(CYAN, strMsgLog);
std::cout << strConsole.toUtf8().data() << std::endl;
}
//for log file
if (!m_bNeedLog)
{
return;
}
ObjectPtr<IBackConsoleController> backConsoleController;
if (backConsoleController.operator bool() && m_backConsole.load())
{
//需要显示日志信息的界面执行显示操作
QMetaObject::invokeMethod(backConsoleController->getObject(),
"sltTextBrowerText",
Q_ARG(QString, strMsgLog + "\r\n\r\n"));
}
QFile file(m_strFileName);
file.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream text_stream(&file);
text_stream << strMsgLog << "\r\n\r\n";
file.close();
}
void DemoLog::deleteLogFile(const QString &strDir, const int& nCount)
{
QDir dir(strDir);
dir.setFilter(QDir::Files);
QList<QFileInfo> fileInfoList = dir.entryInfoList();
if(fileInfoList.size() > nCount)
{
std::sort(fileInfoList.begin(),fileInfoList.end(),[](const QFileInfo &a,const QFileInfo &b)
{
return a.lastModified() > b.lastModified();
});
for(int i = nCount; i < fileInfoList.size();i++)
{
dir.remove(fileInfoList.at(i).fileName());
}
}
}