1 Commits

Author SHA1 Message Date
TianZD 1b2dcb1332 feat: 提供实时日志快照 2026-11-04 18:11:58 +08:00
2 changed files with 35 additions and 0 deletions
+26
View File
@@ -47,6 +47,8 @@ struct LogState
QDate activeDate;
QString currentFilePrefix;
bool installed = false;
std::function<void()> updateCallback; // 回调仅投递通知,不在锁内访问界面或日志。
QStringList recentLines; // 有界缓存最近打印内容;后台线程与界面均通过 mutex 访问。
#if defined(MYLOGGER_TESTING)
// 测试编译时将文件系统副作用收敛到临时目录,并用小阈值快速覆盖分卷逻辑。
QString testLogDirectory;
@@ -313,6 +315,13 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
return;
}
// 只缓存最近打印,避免界面长期运行时无限增长;与文件写入共用锁。
g_logState.recentLines.append(timestamp + QStringLiteral(" ") + msg);
if (g_logState.recentLines.size() > 1000)
g_logState.recentLines.removeFirst();
if (g_logState.updateCallback)
g_logState.updateCallback();
// 跨午夜时先关闭旧日期文件再按新日期选择分卷;轮转失败后的后续消息也会重试打开,
// 这样临时磁盘或权限故障恢复后无需重启应用即可恢复文件日志。
const QDate today = QDate::currentDate();
@@ -416,6 +425,23 @@ bool LogHandler::isInstalled() const
return g_logState.installed;
}
// 回调的安装与清除同样持锁,确保界面销毁后后台线程不再访问接收对象。
void LogHandler::setUpdateCallback(const std::function<void()> &callback)
{
QMutexLocker locker(&g_logState.mutex);
g_logState.updateCallback = callback;
}
// 快照不暴露文件句柄,后台写入和界面轮询不会并发访问 QTextStream。
void LogHandler::snapshot(bool &active, QString &path, qint64 &bytes, QStringList &lines) const
{
QMutexLocker locker(&g_logState.mutex);
active = g_logState.installed && g_logState.file.isOpen();
path = active ? g_logState.file.fileName() : logDirectoryPath();
bytes = active ? g_logState.currentFileBytes : 0;
lines = g_logState.recentLines;
}
#if defined(MYLOGGER_TESTING)
// 测试目录设置在同一把锁下更新,并要求 handler 已卸载,保证没有线程持有旧目录的文件句柄。
void LogHandlerTestAccess::setLogDirectory(const QString &directory)
+9
View File
@@ -2,6 +2,9 @@
#define LOGHANDLER_H
#include <QtCore/qglobal.h>
#include <QString>
#include <QStringList>
#include <functional>
#if defined(MYLOGGER_TESTING)
#include <QString>
@@ -31,6 +34,12 @@ public:
// 返回本库是否仍持有并安装了 Qt 全局消息处理器,供宿主避免重复管理生命周期。
bool isInstalled() const;
// 在同一把锁下读取当前文件、大小和最近日志,供界面安全轮询。
void snapshot(bool &active, QString &path, qint64 &bytes, QStringList &lines) const;
// 设置轻量日志通知;回调在写入线程执行,不能访问日志处理器或界面。
void setUpdateCallback(const std::function<void()> &callback);
// 返回进程内唯一实例;C++11 局部静态对象保证首次构造线程安全。
static LogHandler& Get()
{