| 项 | 值 |
|---|---|
| 项目 | dzs/dzs-ai-content |
| 分支 | v1.0.28 |
| 基准版本 (base) | ee1874ab584b7fd7cb03428bb041ddc1272c7d5e |
| 目标版本 (head) | f82d014d6e6343695e634ff05d7001126b26c99a |
| 变更文件 | 1 个(internal/scheduler/scheduler.go) |
| 变更性质 | 仅日志增强(无业务逻辑变更) |
本次增量只包含 1 个文件、1 个 hunk:internal/scheduler/scheduler.go 中 Dispatcher.executeTask 函数末尾「任务完成,文章已生成」这条 Info 日志,字段由 6 个扩展为 21 个。
@@ -1615,13 +1615,32 @@ func (d *Dispatcher) executeTask(task models.AgentTask) {
obsResult = "ok"
+ qaCommentText := ""
+ if output.QAComment != nil {
+ qaCommentText = *output.QAComment
+ }
log.WithFields(logrus.Fields{
- "article_id": art.ID,
- "status": output.Status,
- "duration": duration,
- "loops": totalLoops,
- "cost": cost,
- "web_search_cnt": len(searchTracer.Traces()),
+ "task_id": task.ID,
+ "agent_id": task.AgentID,
+ "article_id": art.ID,
+ "article_type": art.ArticleType,
+ "column_id": art.ColumnID,
+ "status": output.Status,
+ "title": output.Title,
+ "content_len": len(output.Content),
+ "data_elements": len(output.DataElements),
+ "duration_ms": duration,
+ "loops": totalLoops,
+ "cost": cost,
+ "tokens_input": metrics.TokenInput,
+ "tokens_output": metrics.TokenOutput,
+ "tokens_cached": metrics.TokenCached,
+ "qa_model_source": string(qaSource),
+ "qa_comment": qaCommentText,
+ "web_search_cnt": len(searchTracer.Traces()),
+ "test_trigger": manualTestTrigger,
+ "business_time": businessTime.Format("2006-01-02 15:04:05"),
+ "trigger_source": task.TriggerSource,
}).Info("任务完成,文章已生成")
变更意图明确:把一条「文章生成完成」的结构化日志从「仅记录文章维度」升级为「任务 / Agent / 文章 / 用量 / 质检 / 触发」全维度可观测日志,便于后台「生成记录」与运维排查按 task_id / agent_id / trigger_source 关联检索。
数据来源:
codescan_issues_diff(base=ee1874ab…, head=f82d014d…)
| 指标 | 数量 |
|---|---|
| 修复(fixed,base 有 head 无) | 0 |
| 新增(added,head 有 base 无) | 0 |
两版本质检问题库无差异(修复 0 条 / 新增 0 条)。本次变更未引入任何被质检引擎命中的新问题,也未消除既有问题——符合「纯日志字段扩展」的提交特征。当前 head 版本质量问题总数为 323 条(均为存量跨版本问题,非本次引入)。
对新增日志的 21 个字段逐一核对了字段来源与类型(对照 pkg/models/models.go、internal/database 的 TaskMetrics、本函数局部变量),全部可编译,不存在未定义变量 / 类型不匹配。评审中发现 3 处日志质量问题,均为 Low 级别的可观测性/格式问题,不影响业务正确性:
agent_id 与 column_id 会记录指针地址,而非 ID(Low)task.AgentID 类型为 *int(pkg/models/models.go 的 AgentTask.AgentID *int);art 为 SaveArticle(...) (*models.Article, error) 的返回值,art.ColumnID 类型为 *int(Article.ColumnID *int)。logrus 对非 string / error / fmt.Stringer 的字段值走 fmt.Sprint,对指针会输出内存地址(如 0xc000…)而非其指向的整数。因此新增字段 agent_id、column_id 在日志中很可能落成指针地址,达不到「按 agent/栏目关联排查」的初衷。
"agent_id": ag.ID(ColumnAgent.ID int)、PercentUnitOffenses 观测日志中的 "agent_id": ag.ID,未直接使用 *int 指针。*task.AgentID(此处 task.AgentID 已在上文判空,非 nil)与 *art.ColumnID(若可能为 nil 则用 helper 兜底,如 derefIntOrZero(art.ColumnID))。duration_ms 字段名与单位不符(Low)字段名由 duration 改名为 duration_ms,但取值仍为 duration := int(time.Since(taskStart).Seconds())(秒),buildTaskMetrics 形参也是 durationSeconds。即字段名声称毫秒、实际值是秒,易误导消费方(后台/看板按毫秒解读会得到放大 1000 倍的错误结论)。
duration_s / duration_seconds,或确实改为 time.Since(taskStart).Milliseconds() 后再命名 duration_ms,二者取其一,保持名实一致。business_time 无条件记录,无业务时点时输出零值时间(Low)上文以 businessTime, hasBusinessTime := task.BusinessTime() 取值,随后落库 JSON 时是 if hasBusinessTime { taskResult["business_time"] = … }(条件落),但本日志无条件输出 businessTime.Format("2006-01-02 15:04:05")。当任务无业务时点时(老任务/手工任务),businessTime 为零值,日志将输出 0001-01-01 00:00:00,形成「有值但无意义」的噪声字段,与 taskResult 的口径不一致。
hasBusinessTime 对齐(无业务时点时不落该字段或落空串),或同时附 has_business_time 布尔字段以消除歧义。说明:4.1–4.3 为人工代码评审结论,不属于第三节「修复/新增问题」的真实质检数据;第三节的 0/0 才是质检引擎 diff 结果。此处列出仅供研发参考,不影响本次发布判定。
Info 级日志,未触及任何业务逻辑、控制流、数据写入或第三方接口调用,运行时行为与上一版本一致,无回归风险。agent_id、column_id 的指针解引用,确保日志可被真正用于检索;duration_ms 字段名与单位的一致性;business_time 与 hasBusinessTime 口径对齐,避免零值噪声。
以上均为可观测性优化项,可随下一次提交一并处理,不阻塞本版本发布。