Update 更新文档
This commit is contained in:
202
cleaned_source_code/Sqbase/qlogmanager.cpp
Normal file
202
cleaned_source_code/Sqbase/qlogmanager.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
#include "qlogmanager.h"
|
||||
#include <QTextStream>
|
||||
#include <QCoreApplication>
|
||||
QBasicAtomicPointer<QLogManager> QLogManager::s_instance = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||
QMutex QLogManager::s_mutex;
|
||||
QLogManager::QLogManager(QObject* parent)
|
||||
: QObject(parent),
|
||||
m_minLevel(SQ_INFO),
|
||||
m_workerThread(nullptr),
|
||||
m_running(true)
|
||||
{
|
||||
m_logDirectory = QDir(QCoreApplication::applicationDirPath() + "/logs/");
|
||||
if (!m_logDirectory.exists()) {
|
||||
if (!m_logDirectory.mkpath(".")) {
|
||||
emit newLog(SQ_ERROR, QString("Failed to create log directory: %1").arg(m_logDirectory.path()));
|
||||
}
|
||||
}
|
||||
cleanOldLogs();
|
||||
m_workerThread = new QThread();
|
||||
QObject::connect(m_workerThread, &QThread::started, [this]() {
|
||||
this->processLogs();
|
||||
});
|
||||
m_workerThread->start();
|
||||
}
|
||||
QLogManager::~QLogManager()
|
||||
{
|
||||
m_running = false;
|
||||
m_queueSemaphore.release();
|
||||
if (m_workerThread) {
|
||||
m_workerThread->quit();
|
||||
if (!m_workerThread->wait(3000)) {
|
||||
m_workerThread->terminate();
|
||||
m_workerThread->wait();
|
||||
}
|
||||
delete m_workerThread;
|
||||
}
|
||||
LogEntry entry;
|
||||
while (m_logQueue.dequeue(entry)) {
|
||||
writeToFile(entry.level, entry.message);
|
||||
}
|
||||
for (auto& file : m_openFiles) {
|
||||
if (!file.isNull()) {
|
||||
file->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
QLogManager* QLogManager::Instance()
|
||||
{
|
||||
if (!s_instance.load()) {
|
||||
QMutexLocker locker(&s_mutex);
|
||||
if (!s_instance.load()) {
|
||||
QLogManager* instance = new QLogManager();
|
||||
s_instance.store(instance);
|
||||
qAddPostRoutine(QLogManager::destroyInstance);
|
||||
}
|
||||
}
|
||||
return s_instance.load();
|
||||
}
|
||||
void QLogManager::destroyInstance()
|
||||
{
|
||||
QMutexLocker locker(&s_mutex);
|
||||
QLogManager* instance = s_instance.load();
|
||||
if (instance) {
|
||||
delete instance;
|
||||
s_instance.store(nullptr);
|
||||
}
|
||||
}
|
||||
void QLogManager::setLogLevel(LogLevel level)
|
||||
{
|
||||
QMutexLocker locker(&s_mutex);
|
||||
m_minLevel = level;
|
||||
}
|
||||
void QLogManager::log(LogLevel level, const QString& message, const QString& module)
|
||||
{
|
||||
if (level < m_minLevel) {
|
||||
return;
|
||||
}
|
||||
static thread_local QString lastTimeStr;
|
||||
static thread_local qint64 lastTimeMs = 0;
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
if (now - lastTimeMs > TIMESTAMP_CACHE_DURATION_MS) {
|
||||
lastTimeStr = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
|
||||
lastTimeMs = now;
|
||||
}
|
||||
QString levelStr;
|
||||
switch (level) {
|
||||
case SQ_DEBUG: levelStr = "DEBUG"; break;
|
||||
case SQ_INFO: levelStr = "INFO"; break;
|
||||
case SQ_WARNING: levelStr = "WARNING"; break;
|
||||
case SQ_ERROR: levelStr = "ERROR"; break;
|
||||
case SQ_FATAL: levelStr = "FATAL"; break;
|
||||
}
|
||||
QString logLine = QString("[%1][%2][%3] %4")
|
||||
.arg(lastTimeStr, levelStr, module, message);
|
||||
emit newLog(level, logLine);
|
||||
LogEntry entry;
|
||||
entry.level = level;
|
||||
entry.message = logLine;
|
||||
entry.timestamp = now;
|
||||
m_logQueue.enqueue(entry);
|
||||
m_queueSemaphore.release();
|
||||
}
|
||||
void QLogManager::processLogs()
|
||||
{
|
||||
while (m_running) {
|
||||
m_queueSemaphore.acquire();
|
||||
LogEntry entry;
|
||||
while (m_logQueue.dequeue(entry)) {
|
||||
writeToFile(entry.level, entry.message);
|
||||
if (!m_running) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
QString QLogManager::getLogFileName(LogLevel level)
|
||||
{
|
||||
QString levelStr;
|
||||
switch (level) {
|
||||
case SQ_DEBUG: levelStr = "debug"; break;
|
||||
case SQ_INFO: levelStr = "info"; break;
|
||||
case SQ_WARNING: levelStr = "warning"; break;
|
||||
case SQ_ERROR: levelStr = "error"; break;
|
||||
case SQ_FATAL: levelStr = "fatal"; break;
|
||||
default: levelStr = "system"; break;
|
||||
}
|
||||
return QString("%1_%2.log")
|
||||
.arg(levelStr)
|
||||
.arg(QDateTime::currentDateTime().toString("yyyyMMdd"));
|
||||
}
|
||||
void QLogManager::writeToFile(LogLevel level, const QString& logLine)
|
||||
{
|
||||
try {
|
||||
if (!m_openFiles.contains(level)) {
|
||||
QString fileName = m_logDirectory.filePath(getLogFileName(level));
|
||||
QSharedPointer<QFile> file(new QFile(fileName));
|
||||
if (!file->open(QIODevice::WriteOnly | QIODevice::Append)) {
|
||||
emit newLog(SQ_ERROR, QString("[LogSystem] Failed to open log file: %1").arg(fileName));
|
||||
return;
|
||||
}
|
||||
m_openFiles[level] = file;
|
||||
}
|
||||
if (!m_openFiles[level].isNull()) {
|
||||
QTextStream stream(m_openFiles[level].data());
|
||||
stream << logLine << "\n";
|
||||
stream.flush();
|
||||
if (m_openFiles[level]->size() > MAX_FILE_SIZE) {
|
||||
rotateLogFile(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
emit newLog(SQ_ERROR, "[LogSystem] Exception occurred while writing log");
|
||||
}
|
||||
}
|
||||
void QLogManager::rotateLogFile(LogLevel level)
|
||||
{
|
||||
if (!m_openFiles.contains(level)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
m_openFiles[level]->close();
|
||||
QString oldName = m_logDirectory.filePath(getLogFileName(level));
|
||||
QString newName = oldName + "." + QDateTime::currentDateTime().toString("hhmmsszzz");
|
||||
if (!QFile::rename(oldName, newName)) {
|
||||
emit newLog(SQ_ERROR, QString("[LogSystem] Failed to rotate log file from %1 to %2")
|
||||
.arg(oldName, newName));
|
||||
}
|
||||
m_openFiles.remove(level);
|
||||
}
|
||||
catch (...) {
|
||||
emit newLog(SQ_ERROR, "[LogSystem] Exception occurred while rotating log file");
|
||||
}
|
||||
}
|
||||
void QLogManager::cleanOldLogs()
|
||||
{
|
||||
try {
|
||||
QStringList logFiles = m_logDirectory.entryList(QStringList() << "*.log" << "*.log.*", QDir::Files);
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
for (const QString& fileName : logFiles) {
|
||||
QFileInfo fileInfo(m_logDirectory.filePath(fileName));
|
||||
if (fileInfo.lastModified().daysTo(now) > MAX_LOG_DAYS) {
|
||||
if (!QFile::remove(fileInfo.absoluteFilePath())) {
|
||||
emit newLog(SQ_WARNING, QString("Failed to remove old log file: %1")
|
||||
.arg(fileInfo.absoluteFilePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
emit newLog(SQ_ERROR, "[LogSystem] Exception occurred while cleaning old logs");
|
||||
}
|
||||
}
|
||||
void QLogManager::flush()
|
||||
{
|
||||
QMutexLocker locker(&s_mutex);
|
||||
for (auto& file : m_openFiles) {
|
||||
if (!file.isNull()) {
|
||||
file->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user