fix(log_box/LogMonitor): 修复log_box及LogMonitor在跨零点时采集节点与日志历史丢失的问题 - #626
Conversation
任务运行期间脚本日志按天滚动(跨零点)后,会话收尾只读得到新文件,滚动前采集的节点详情在任务报告中丢失。缺省与运行日志监控(LogMonitor)同一逻辑:重命名不改变 inode,在同目录找回被轮换的旧文件并从未读 offset 续读,不依赖命名猜测、不误读同名旧残留;文件系统不提供 inode 时仅回退 .bak 通用约定,日期式命名不在通用组件里猜测。zzz-od / OK-WW / OK-NTE 经 get_collect 的 rotated_name 模板声明各自滚动命名,并修正 sink 回调类型标注与实际三参契约一致。
固定路径监控下脚本把日志重命名滚动(如跨零点 log.txt → log.txt.YYYY-MM-DD)时,原实现清空已读累积内容且备份补偿参数无调用方使用,落库历史只剩零点后内容。改为保留滚动前后累积内容,按 inode 在同目录找回被重命名的旧文件并续读未读尾部(不依赖命名猜测);移除无人使用的 bak_log_path 参数。
审查者指南本 PR 通过在 log_box 与 LogMonitor 中保留轮转前状态、按 inode 找回被重命名的旧日志并从原 offset 续读未读尾部,解决跨零点后运行日志历史和报告节点详情丢失;同时为日期式轮转增加显式 日志轮转恢复时序图sequenceDiagram
participant LogMonitor
participant LogSource
participant CurrentLog
participant RotatedLog
participant Report
LogMonitor->>CurrentLog: stat()
LogMonitor->>LogSource: read_new()
CurrentLog-->>LogSource: file identity changes
LogSource->>RotatedLog: _find_rotated_file(old_ino)
RotatedLog-->>LogSource: renamed old file
LogSource->>RotatedLog: _read_from(offset)
RotatedLog-->>LogSource: unread tail
LogSource->>CurrentLog: _read_tail()
CurrentLog-->>LogSource: new-file lines
LogSource->>Report: preserve history and append recovered lines
文件级变更
提示与命令与 Sourcery 交互
自定义使用体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's Guide本 PR 通过在 log_box 与 LogMonitor 中保留轮转前状态、按 inode 找回被重命名的旧日志并从原 offset 续读未读尾部,解决跨零点后运行日志历史和报告节点详情丢失;同时为日期式轮转增加显式 Sequence diagram for log rotation recoverysequenceDiagram
participant LogMonitor
participant LogSource
participant CurrentLog
participant RotatedLog
participant Report
LogMonitor->>CurrentLog: stat()
LogMonitor->>LogSource: read_new()
CurrentLog-->>LogSource: file identity changes
LogSource->>RotatedLog: _find_rotated_file(old_ino)
RotatedLog-->>LogSource: renamed old file
LogSource->>RotatedLog: _read_from(offset)
RotatedLog-->>LogSource: unread tail
LogSource->>CurrentLog: _read_tail()
CurrentLog-->>LogSource: new-file lines
LogSource->>Report: preserve history and append recovered lines
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
您好——我发现了 1 个问题
给 AI 代理的提示
请处理本次代码审查中的评论:
## 单独评论
### 评论 1
<location path="app/utils/LogMonitor.py" line_range="196-199" />
<code_context>
+ # 同一次运行,log_contents 与 if_log_start 保留不清空,否则
+ # 落库历史只剩轮转后内容(跨零点实测);被重命名的旧文件按
+ # inode 在同目录找回,把未读尾部接回来
if (
log_stat.st_ino != current_path.stat().st_ino
or log_stat.st_size > current_path.stat().st_size
):
+ if_log_start = await self._recover_rotated_tail(
+ current_path,
</code_context>
<issue_to_address>
**问题 (bug_risk):** LogMonitor 仅通过 `st_ino`(或文件大小减小)来检测文件替换或轮转。在对每个文件都报告 `st_ino == 0` 的文件系统上,如果替换后的新文件已经增长到超过之前的偏移量,就无法检测到文件替换,因此监控会从旧偏移量开始读取,永久跳过新日志的开头部分。
**触发条件:** 当被监控的日志在 inode 值不可用的文件系统上发生轮转或替换,并且新文件在下一次轮询前增长到超过之前文件的偏移量时。
**建议修复:** 跟踪其他身份字段,例如创建时间/变更时间;或者显式处理 `st_ino == 0`,在重新初始化偏移量之前,通过其他可靠的文件身份信号检测文件是否已被替换。
</issue_to_address>Sourcery 评估
需要人工审查。 当前有 1 个发现需要优先处理;如果 inode 恢复或修改后的轮转处理选择了错误的文件或偏移量,过时或重复的日志行可能会被追加到任务历史和报告中,而被移除的监控参数可能会导致现有调用方在运行时出错。回滚可以避免进一步影响,但无法移除已经持久化的不正确历史记录或已对外展示的报告。
阻塞性发现:app/utils/LogMonitor.py:199
Original comment in English
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="app/utils/LogMonitor.py" line_range="196-199" />
<code_context>
+ # 同一次运行,log_contents 与 if_log_start 保留不清空,否则
+ # 落库历史只剩轮转后内容(跨零点实测);被重命名的旧文件按
+ # inode 在同目录找回,把未读尾部接回来
if (
log_stat.st_ino != current_path.stat().st_ino
or log_stat.st_size > current_path.stat().st_size
):
+ if_log_start = await self._recover_rotated_tail(
+ current_path,
</code_context>
<issue_to_address>
**issue (bug_risk):** LogMonitor detects replacement or rotation only through `st_ino` (or a size decrease). On filesystems that report `st_ino == 0` for every file, a replacement whose new file has already grown beyond the previous offset is not detected, so monitoring seeks from the old offset and permanently skips the beginning of the new log.
**Triggers:** When the monitored log is rotated or replaced on a filesystem without usable inode values and the new file grows past the previous file offset before the next polling iteration.
**Suggested fix:** Track an additional identity field such as creation/change time, or explicitly handle `st_ino == 0` by detecting replacement through another reliable file identity signal before reinitializing the offset.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 1 finding to address first, and if inode recovery or the revised rollover handling selects the wrong file or offset, stale or duplicated log lines can be appended to task history and reports, and the removed monitor argument could break existing callers at runtime. Reverting prevents further impact but does not remove incorrect history or externally visible reports already persisted.
Blocking findings: app/utils/LogMonitor.py:199
Sourcery 审查指出:st_ino 恒为 0 的文件系统(FAT32/exFAT/部分网络盘)上,若新文件在单个轮询周期内长过旧 offset,仅靠 st_ino 比对 + size 缩小检不出替换,监控会从旧 offset 续读新文件、永久跳过其开头。检测身份对齐 LogSource 的 (st_ino, st_ctime_ns) 双信号(Windows 下 ctime 为创建时间,同文件追加不变、被替换才变化),非隧道场景可检出;检出后保留已读历史并从头读取新文件。
|
@qiyinxi review |
|
静态审 + 本地跑了 建议修
其他
核对过没问题的: OkNte 的 |
…ation # Conflicts: # CHANGELOG.md
PR 审查(真机复现)发现:声明 rotated_name 后完全跳过 inode 找回,会话内日志因删除重建等非重命名原因换身份时会进入轮转分支,候选探测命中昨天残留的轮转产物(上次零点轮转的正常产物几乎总在),offset 夹零时把旧日志整份错当本次运行内容推给任务报告。改为有 inode 一律按 inode 在同目录精确找回,未命中宁缺勿错、声明模板也不猜名字;rotated_name 仅在文件系统不提供 inode(FAT32/exFAT/网络盘)时按昨天/今天生成候选生效,未声明回退 .bak 约定。
|
第二轮( 必修
其他(不用改,给维护者)
核对过没问题的: 静态审 + 上面两处真机复现,未跑仓库测试套件、未跑前端。 |
PR 审查(真机复现)发现:inode 轮转分支排空旧文件后未像路径切换分支那样刷新 last_callback_time。旧文件在轮转前一轮已读空时找回一行未得、无行触发回调,last_callback_time 停在轮转前;无日期时间格式(ZZZ-OD 的 %H:%M:%S.%f)的跨零点首行经 update_latest_timestamp 按该旧锚补日期,latest_time 落到 24 小时前,check_log 判定运行超时并中止任务(dev 上轮转会重置 if_log_start、这些行不进时间判定,故为本 PR 新引入)。与路径切换分支对齐:找回之后刷新。
|
第三轮( 实跑(py 3.12 / NTFS,把三个版本的
顺带更正我上一轮的一句话:「受影响的只有 ZZZ-OD」范围写窄了。OK-NTE( 核对过没问题的: 静态审 + 上述实跑,未跑仓库测试套件、未跑前端。 |
…ation # Conflicts: # res/version.json
摘要
rotated_name参数:日期式滚动命名(如 zzz-od 的log.txt.YYYY-MM-DD、OK 系的ok-script.YYYY-MM-DD.log)由各专项声明 strftime 模板,文件系统不提供 inode 时这是唯一兜底;zzz-od / OK-WW / OK-NTE 专项已接入Sourcery 摘要
修复跨零点日志轮转导致的运行日志和节点详情丢失,并完善不同轮转命名方式的日志采集补偿支持。
新功能:
rotated_name配置,支持按日期模板定位轮转日志。Bug 修复:
增强功能:
文档:
rotated_name的接入说明。Original summary in English
Sourcery 摘要
防止跨午夜日志轮换导致运行时历史记录丢失,以及已收集的节点详细信息丢失。
新功能:
错误修复:
增强功能:
文档:
rotated_name的用法、支持的轮换模式,以及适配器集成中的常见问题。Original summary in English
Sourcery 摘要
在午夜日志轮换期间保留运行时日志历史记录和已收集的节点详细信息,同时扩展对基于日期的轮换名称的恢复支持。
新功能:
错误修复:
增强功能:
文档:
Original summary in English
Summary by Sourcery
保留跨零点日志轮转期间的运行日志和节点详情,并完善不同文件系统与命名方式下的轮转日志恢复支持。
New Features:
rotated_name配置,支持在无 inode 文件系统上按日期模板定位轮转日志。Bug Fixes:
Enhancements:
Documentation:
rotated_name用法及专项适配注意事项。Original summary in English
Summary by Sourcery
保留跨零点日志轮转期间的运行日志和节点详情,并完善不同文件系统与命名方式下的轮转日志恢复支持。
New Features:
rotated_name配置,支持在无 inode 文件系统上按日期模板定位轮转日志。Bug Fixes:
Enhancements:
Documentation:
rotated_name用法及专项适配注意事项。Original summary in English