5#include "RabbitCommonDir.h"
12#ifdef HAVE_RABBITCOMMON_GUI
13 #include <QDesktopServices>
15#include <QRegularExpression>
19#include <QCoreApplication>
20#ifdef HAVE_RABBITCOMMON_GUI
21#include "DockDebugLog.h"
25#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
26 QtMessageHandler g_originalMessageHandler = Q_NULLPTR;
28 QtMsgHandler g_originalMessageHandler = Q_NULLPTR;
34static Q_LOGGING_CATEGORY(Logger,
"RabbitCommon.log")
35QRegularExpression g_reInclude;
36QRegularExpression g_reExclude;
38CLog::CLog() : QObject(),
39 m_szFileFormat("yyyy-MM-dd"),
43 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
44 QSettings::IniFormat);
46 SetFilter(set.value(
"Log/Filter/include").toString(),
47 set.value(
"Log/Filter/Exclude").toString());
49 QString szPattern =
"[%{time hh:mm:ss.zzz} %{pid}|%{threadid} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}E%{endif}%{if-fatal}F%{endif}] %{category} - %{message}";
50#ifdef QT_MESSAGELOGCONTEXT
52 szPattern +=
" [%{file}:%{line}, %{function}]";
53#elif defined(DEBUG) || defined(_DEBUG)
54 szPattern +=
" [%{file}:%{line}, %{function}]";
56 QString szFilterRules;
57 quint64 nInterval = 60;
58#if !(defined(DEBUG) || defined(_DEBUG) || ANDROID)
59 szFilterRules =
"*.debug = false";
62 m_szPath = CDir::Instance()->GetDirLog();
63 QString szConfFile = RabbitCommon::CDir::Instance()->GetDirConfig()
64 + QDir::separator() + qApp->applicationName() +
"_logqt.ini";
65 szConfFile = set.value(
"Log/ConfigFile", szConfFile).toString();
66 if(!QFile::exists(szConfFile))
67 szConfFile = RabbitCommon::CDir::Instance()->GetDirConfig()
68 + QDir::separator() +
"logqt.in";
69 if (QFile::exists(szConfFile))
71 m_szConfigureFile = szConfFile;
72 qInfo(Logger) <<
"Load log configure file:" << m_szConfigureFile;
73 QSettings setConfig(m_szConfigureFile, QSettings::IniFormat);
74 setConfig.beginGroup(
"Log");
75 m_szPath = setConfig.value(
"Path", m_szPath).toString();
76 m_szFileFormat = setConfig.value(
"Name", m_szFileFormat).toString();
77 szPattern = setConfig.value(
"Pattern", szPattern).toString();
78 nInterval = setConfig.value(
"Interval", nInterval).toUInt();
79 m_nCount = setConfig.value(
"Count", 0).toULongLong();
80 QString szLength = setConfig.value(
"Length", 0).toString();
81 if(!szLength.isEmpty()) {
82 QRegularExpression e(
"(\\d+)([mkg]?)",
83 QRegularExpression::CaseInsensitiveOption);
84 QRegularExpressionMatch m;
85 if(szLength.contains(e, &m) && m.hasMatch())
88 if(m.capturedLength(1) > 0)
89 len = m.captured(1).toULong();
90 if(m.capturedLength(2) > 0)
92 QString u = m.captured(2).toUpper();
103 setConfig.endGroup();
105 setConfig.beginGroup(
"Rules");
106 auto keys = setConfig.childKeys();
108 szFilterRules.clear();
109 foreach(
auto k, keys) {
110 QString v = setConfig.value(k).toString();
111 szFilterRules += k +
"=" + v +
"\n";
113 setConfig.endGroup();
115 qWarning(Logger) <<
"Log configure file is not exist:" << szConfFile
116 <<
". Use default settings.";
119 qDebug(Logger) <<
"Log configure:"
120 <<
"\n Path:" << m_szPath
121 <<
"\n FileNameFormat:" << m_szFileFormat
122 <<
"\n szPattern:" << szPattern
123 <<
"\n Interval:" << nInterval
124 <<
"\n Count:" << m_nCount
125 <<
"\n Length:" << m_nLength
126 <<
"\n Rules:" << szFilterRules;
128 if(!szFilterRules.isEmpty())
129 QLoggingCategory::setFilterRules(szFilterRules);
131 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
132 qSetMessagePattern(szPattern);
133 g_originalMessageHandler = qInstallMessageHandler(myMessageOutput);
135 g_originalMessageHandler = qInstallMsgHandler(myMessageOutput);
139 if(!d.exists(m_szPath))
141 if(!d.mkpath(m_szPath))
142 fprintf(stderr,
"Create log directory fail. %s\n",
143 m_szPath.toStdString().c_str());
148 bool check = connect(&m_Timer, SIGNAL(timeout()),
149 this, SLOT(slotTimeout()));
151 m_Timer.start(nInterval * 1000);
158 if(m_Timer.isActive())
162CLog* CLog::Instance()
164 static CLog* p = NULL;
172QString CLog::GetLogFile()
174 return m_File.fileName();
177QString CLog::OpenLogConfigureFile()
179 return m_szConfigureFile;
182QString CLog::GetLogDir()
184 QString f = GetLogFile();
185 if(f.isEmpty())
return f;
188 return fi.absolutePath();
191int CLog::SetFilter(
const QString &szInclude,
const QString &szExclude)
193 g_reInclude = QRegularExpression(szInclude);
194 g_reExclude = QRegularExpression(szExclude);
196 QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
197 QSettings::IniFormat);
198 set.setValue(
"Log/Filter/include", szInclude);
199 set.setValue(
"Log/Filter/Exclude", szExclude);
203int CLog::GetFilter(QString &szInclude, QString &szExclude)
205 szInclude = g_reInclude.pattern();
206 szExclude = g_reExclude.pattern();
210#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
211void CLog::myMessageOutput(QtMsgType type,
212 const QMessageLogContext &context,
216 #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
217 szMsg = qFormatLogMessage(type, context, msg);
222 if(g_reInclude.isValid() && !g_reInclude.pattern().isEmpty()) {
223 QRegularExpressionMatch m = g_reInclude.match(szMsg);
228 if(g_reExclude.isValid() && !g_reExclude.pattern().isEmpty()) {
229 QRegularExpressionMatch m = g_reExclude.match(szMsg);
235#ifdef HAVE_RABBITCOMMON_GUI
237 emit g_pDcokDebugLog->sigAddLog(szMsg);
249 if(CLog::Instance()->m_File.isOpen())
251 QTextStream s(&CLog::Instance()->m_File);
252 CLog::Instance()->m_Mutex.lock();
253 s << szMsg <<
"\r\n";
255 CLog::Instance()->m_Mutex.unlock();
260 if(g_originalMessageHandler)
261 g_originalMessageHandler(type, context, msg);
264void CLog::myMessageOutput(QtMsgType type,
const char* msg)
268 if(g_reInclude.isValid() && !g_reInclude.pattern().isEmpty()) {
269 QRegularExpressionMatch m = g_reInclude.match(szMsg);
274 if(g_reExclude.isValid() && !g_reExclude.pattern().isEmpty()) {
275 QRegularExpressionMatch m = g_reExclude.match(szMsg);
290 if(CLog::Instance()->m_File.isOpen())
292 QTextStream s(&CLog::Instance()->m_File);
293 CLog::Instance()->m_Mutex.lock();
294 s << szMsg <<
"\r\n";
295 CLog::Instance()->m_Mutex.unlock();
300 if(g_originalMessageHandler)
301 g_originalMessageHandler(type, msg);
305void CLog::checkFileCount()
307 if(m_nCount < 2)
return;
310 auto lstFiles = d.entryInfoList(QDir::Files, QDir::Time);
311 if(lstFiles.size() < m_nCount)
return;
313 if(lstFiles.first().lastModified() < lstFiles.back().lastModified())
315 if(d.remove(lstFiles.first().absoluteFilePath()))
316 qInfo(Logger) <<
"Remove file:" << lstFiles.first().absoluteFilePath();
318 qCritical(Logger) <<
"Remove file fail:"
319 << lstFiles.first().absoluteFilePath();
321 if(d.remove(lstFiles.back().absoluteFilePath()))
322 qInfo(Logger) <<
"Remove file:" << lstFiles.back().absoluteFilePath();
324 qCritical(Logger) <<
"Remove file fail:"
325 << lstFiles.back().absoluteFilePath();
329QString CLog::getFileName()
332 QString szNo = QString(
"%1").arg(1, 4, 10, fill);
338 szFile = m_File.fileName();
339 if(!szFile.isEmpty())
return szFile;
341 szName = QDate::currentDate().toString(m_szFileFormat);
342 d.setNameFilters(QStringList() << szName +
"*");
343 auto lstFiles = d.entryInfoList(QDir::Files, QDir::Name);
345 if(lstFiles.isEmpty())
346 szFile = m_szPath + QDir::separator() + szName + szSep + szNo +
".log";
348 szFile = lstFiles.back().absoluteFilePath();
353QString CLog::getNextFileName(
const QString szFile)
358 QFileInfo fi(szFile);
360 QString szNo = QString(
"%1").arg(1, 4, 10, fill);
362 QString szName = fi.baseName();
364 auto s = szName.split(szSep);
366 && QDate::currentDate().toString(m_szFileFormat) == s[0])
370 szNo = QString(
"%1").arg(szNo.toInt() + 1, 4, 10, fill);
375 szName = QDate::currentDate().toString(m_szFileFormat);
378 szName += szSep + szNo;
379 return m_szPath + QDir::separator() + szName +
".log";
382bool CLog::checkFileLength()
384 if(m_nLength == 0)
return false;
386 if(m_File.fileName().isEmpty())
return false;
388 QFileInfo fi(m_File.fileName());
390 if(fi.size() < m_nLength)
return false;
398void CLog::slotTimeout()
401 if(m_File.fileName().isEmpty())
403 szFile = getFileName();
404 m_File.setFileName(szFile);
408 if(checkFileLength())
409 szFile = getNextFileName(m_File.fileName());
411 if(m_File.isOpen())
break;
413 if(szFile.isEmpty())
return;
415 Q_ASSERT(!szFile.isEmpty());
421 m_File.setFileName(szFile);
422 if(!m_File.open(QFile::WriteOnly | QFile::Append))
425 fprintf(stderr,
"Open log file fail. %s\n",
426 m_File.fileName().toStdString().c_str());
434#ifdef HAVE_RABBITCOMMON_GUI
436void OpenLogConfigureFile()
438 QString f = RabbitCommon::CLog::Instance()->OpenLogConfigureFile();
441 qCritical(Logger) <<
"Configure file is empty";
444 QDesktopServices::openUrl(QUrl::fromLocalFile(f));
449 QString d = RabbitCommon::CLog::Instance()->GetLogFile();
452 qCritical(Logger) <<
"Log file is empty";
455 QDesktopServices::openUrl(d);
460 QString f = RabbitCommon::CLog::Instance()->GetLogDir();
463 qCritical(Logger) <<
"Log folder is empty";
466 QDesktopServices::openUrl(QUrl::fromLocalFile(f));