////#include "qlogmanager.h" ////#include ////#include ////#include ////#include //// ////QLogManager* QLogManager::instance = nullptr; //// ////QLogManager::QLogManager(QObject* parent) : QObject(parent) { //// // 创建日志目录 //// logDirectory = QDir::currentPath() + "/logs/"; //// QDir dir; //// if (!dir.exists(logDirectory)) { //// dir.mkpath(logDirectory); //// } //// //// // 清理旧日志 //// cleanOldLogs(); ////} //// ////QLogManager* QLogManager::getInstance() { //// static QMutex mutex; //// QMutexLocker locker(&mutex); //// if (!instance) { //// instance = new QLogManager; //// } //// return instance; ////} //// ////void QLogManager::log(LogLevel level, const QString& message, const QString& module) { //// QMutexLocker locker(&mutex); //// QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); //// 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(timestamp, levelStr, module, message); //// //// // 输出到控制台 //// emit newLog(level, logLine); //// //// // 写入文件 //// writeToFile(level, logLine); ////} //// ////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) { //// // 为不同级别的日志创建不同文件 //// QString logFileName = logDirectory + getLogFileName(level); //// QFile file(logFileName); //// //// if (file.open(QIODevice::WriteOnly | QIODevice::Append)) { //// QTextStream stream(&file); //// stream << logLine << "\n"; //// file.close(); //// } else { //// // 如果文件打开失败,发出错误日志 //// emit newLog(SQ_ERROR, QString("[LogSystem] Failed to open log file: %1").arg(logFileName)); //// } ////} //// ////void QLogManager::cleanOldLogs() { //// QDir dir(logDirectory); //// QStringList logFiles = dir.entryList(QStringList() << "*.log", QDir::Files); //// //// QDateTime now = QDateTime::currentDateTime(); //// for (const QString& fileName : logFiles) { //// QFileInfo fileInfo(dir.filePath(fileName)); //// if (fileInfo.lastModified().daysTo(now) > maxLogDays) { //// QFile::remove(fileInfo.absoluteFilePath()); //// } //// } ////} //#include "qlogmanager.h" //#include //#include //#include //#include //#include //#include // //QLogManager* QLogManager::instance = nullptr; //const int QLogManager::maxLogDays = 7; //const qint64 QLogManager::maxFileSize = 10 * 1024 * 1024; // 10MB // //QLogManager::QLogManager(QObject* parent) : QObject(parent), minLevel(SQ_INFO), running(true) { // // 创建日志目录 - 修正exists检查 // logDirectory = QDir::currentPath() + "/logs/"; // QDir dir(logDirectory); // 使用QString构造QDir // if (!dir.exists()) { // 无参数调用exists() // if (!dir.mkpath(".")) { // QString msg = "Failed to create log directory:" + logDirectory.path(); // emit newLog(SQ_WARNING, msg); // } // } // // // 清理旧日志 // cleanOldLogs(); // // // 启动工作线程 // workerThread = new QThread(); // QObject::connect(workerThread, &QThread::started, [this]() { // this->processLogs(); // }); // workerThread->start(); // //workerThread = QThread::create([this] { processLogs(); }); // //workerThread->start(); //} // //QLogManager::~QLogManager() { // if (workerThread) { // workerThread->quit(); // workerThread->wait(); // delete workerThread; // } // // running = false; // queueSemaphore.release(); // 唤醒线程以退出 // // // 关闭所有打开的文件 // for (auto& file : openFiles) { // if (!file.isNull()) { // file->close(); // } // } //} // //QLogManager* QLogManager::getInstance() { // static QMutex mutex; // QMutexLocker locker(&mutex); // if (!instance) { // instance = new QLogManager; // } // return instance; //} // //void QLogManager::setLogLevel(LogLevel level) { // QMutexLocker locker(&mutex); // minLevel = level; //} // //void QLogManager::log(LogLevel level, const QString& message, const QString& module) { // if (level < minLevel) { // return; // } // // // 优化时间戳获取 // static thread_local QString lastTimeStr; // static thread_local qint64 lastTimeMs = 0; // // qint64 now = QDateTime::currentMSecsSinceEpoch(); // if (now - lastTimeMs > 100) { // 每100ms更新一次 // 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); // // // 快速入队 // { // QMutexLocker locker(&mutex); // logQueue.enqueue(qMakePair(level, logLine)); // } // queueSemaphore.release(); // 通知工作线程 //} // //void QLogManager::processLogs() { // while (running) { // queueSemaphore.acquire(); // 等待新日志 // // QPair logEntry; // { // QMutexLocker locker(&mutex); // if (!logQueue.isEmpty()) { // logEntry = logQueue.dequeue(); // } // } // // if (!logEntry.second.isEmpty()) { // writeToFile(logEntry.first, logEntry.second); // } // } // // // 退出前处理剩余日志 // while (true) { // QPair logEntry; // { // QMutexLocker locker(&mutex); // if (logQueue.isEmpty()) break; // logEntry = logQueue.dequeue(); // } // writeToFile(logEntry.first, logEntry.second); // } //} // //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) { //// if (!openFiles.contains(level)) { //// QString fileName = logDirectory.path() + getLogFileName(level); //// QSharedPointer file(new QFile(fileName)); //// if (file->open(QIODevice::WriteOnly | QIODevice::Append)) { //// openFiles[level] = file; //// } //// else { //// emit newLog(SQ_ERROR, QString("[LogSystem] Failed to open log file: %1").arg(fileName)); //// return; //// } //// } //// //// if (!openFiles[level].isNull()) { //// QTextStream stream(openFiles[level].data()); //// stream << logLine << "\n"; //// //// // 检查文件大小,超过限制则滚动 //// if (openFiles[level]->size() > maxFileSize) { //// openFiles[level]->close(); //// openFiles.remove(level); //// //// // 添加时间戳到旧文件名 //// QString oldName = logDirectory + getLogFileName(level); //// QString newName = oldName + "." + QDateTime::currentDateTime().toString("hhmmsszzz"); //// QFile::rename(oldName, newName); //// } //// } ////} // //void QLogManager::writeToFile(LogLevel level, const QString& logLine) //{ // // 检查并维护打开的文件 // if (!openFiles.contains(level)) { // QString fileName = logDirectory.path()+"/" + getLogFileName(level); // QSharedPointer file(new QFile(fileName)); // if (file->open(QIODevice::WriteOnly | QIODevice::Append)) { // openFiles[level] = file; // } // else { // emit newLog(SQ_ERROR, QString("[LogSystem] Failed to open log file: %1").arg(fileName)); // return; // } // } // // // 修正:避免创建临时QTextStream // if (!openFiles[level].isNull()) { // QTextStream stream(openFiles[level].data()); // stream << logLine << "\n"; // stream.flush(); // 确保立即写入 // // // 检查文件大小 // if (openFiles[level]->size() > maxFileSize) { // rotateLogFile(level); // } // } //} // //void QLogManager::rotateLogFile(LogLevel level) //{ // if (!openFiles.contains(level)) return; // // openFiles[level]->close(); // // QString oldName = logDirectory.path() + getLogFileName(level); // QString newName = oldName + "." + QDateTime::currentDateTime().toString("hhmmsszzz"); // // QFile::rename(oldName, newName); // openFiles.remove(level); //} // //void QLogManager::cleanOldLogs() { // QDir dir(logDirectory); // QStringList logFiles = dir.entryList(QStringList() << "*.log" << "*.log.*", QDir::Files); // // QDateTime now = QDateTime::currentDateTime(); // for (const QString& fileName : logFiles) { // QFileInfo fileInfo(dir.filePath(fileName)); // if (fileInfo.lastModified().daysTo(now) > maxLogDays) { // QFile::remove(fileInfo.absoluteFilePath()); // } // } //} // //void QLogManager::flush() { // QMutexLocker locker(&mutex); // for (auto& file : openFiles) { // if (!file.isNull()) { // file->flush(); // } // } //} // qlogmanager.cpp // qlogmanager.h #include "qlogmanager.h" #include #include QBasicAtomicPointer 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)) { // 等待3秒 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 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(); } } }