Files
zt-closet-backend/.codebuddy/plans/按层区分_DAO_span_命名_72d9748c.md
T
2026-09-11 01:41:52 +08:00

6.9 KiB
Raw Blame History

name, overview, todos
name overview todos
按层区分 DAO span 命名 将 mysqldao 的 span 名由 dao.X 改为 mysqldao.X、redisdao 的改为 redisdao.X,共 140 处,解决两层 span 名无法区分的问题。
id content status
rename-mysqldao 批量替换 internal/mysqldao 下 109 处 span 前缀为 mysqldao. completed
id content status
rename-redisdao 批量替换 internal/redisdao 下 31 处 span 前缀为 redisdao. completed
id content status dependencies
verify-rename 用 [subagent:code-explorer] 复核前缀计数与无残留无错改 completed
rename-mysqldao
rename-redisdao
id content status dependencies
sync-readme 在 README 目录说明中补充 span 命名约定 completed
verify-rename
id content status dependencies
build-verify 执行 go build ./... 与 go vet ./... 验证 completed
verify-rename
sync-readme

产品概述

统一调整 OTel span 命名前缀:数据访问层的 span 名由通用的 dao.XXX 改为可区分来源的 mysqldao.XXX 与 redisdao.XXX,解决 MySQL 与 Redis 两层调用在链路追踪中无法区分的问题。

核心功能

  • MySQL 层改名:internal/mysqldao/ 下全部 109 处 span 名前缀 dao. 改为 mysqldao.
  • Redis 层改名:internal/redisdao/ 下全部 31 处 span 名前缀 dao. 改为 redisdao.
  • 命名一致性保持:仅改前缀,方法名(如 UserInfoSet)、业务逻辑、其他 span 属性均不变
  • 不影响其他层:internal/service(service.)、pkg/upload(upload.)、pkg/tokenhub(scheduler.)保持原样
  • 可维护性:README 目录说明补一句 span 命名约定,避免后续新增代码再用回 dao.

技术栈

  • Go 1.27,模块 git.lzcwy.cn/zhengchiliu/zt-closet-backend
  • OpenTelemetry Trace(global.Tracer,OTLP gRPC 上报)
  • span 创建统一写法:ctx, span := global.Tracer.Start(ctx, "<前缀>.<方法名>")

实现方案

采用目录限定的批量字符串替换:把 global.Tracer.Start(ctx, "dao. 中的前缀分别替换为 mysqldao. / redisdao.,替换范围严格限定在 internal/mysqldao/ 与 internal/redisdao/ 两个目录。

关键决策与取舍:

  1. 前缀命名用 mysqldao. / redisdao. 而非 mysql. / redis.:与包名(package mysqldao / package redisdao)完全一致,Go 项目中 span 名即包名+方法名,排查时可从 span 名直接定位到文件与包,无需映射记忆。
  2. 批量 sed 而非逐处手改:140 处手工改必漏;用 sed -i 's/Tracer\.Start(ctx, "dao\./Tracer.Start(ctx, "mysqldao./g' 这类按目录执行的命令可保证一致性与完整性,且模式串锚定了 Tracer.Start(ctx, "dao. 全串,不会误伤字符串变量、注释或日志中的 dao.。
  3. 只改前缀,不改方法名:方法名与所在函数名一一对应,改名会造成与函数名不一致的二次困惑;同时避免破坏任何按名称检索的既有习惯。
  4. 不引入常量:项目其余前缀(service.、upload.、scheduler.)均为字面量,沿用字面量保持风格统一,不引入新的抽象层(YAGNI)。
  5. 不改动 service / upload / tokenhub:这些层前缀本身已能区分,不属于本次「分不清」的范围,缩小改动面。

性能与可靠性:

  • span 名为启动期/调用期构造的字符串常量,改为更长前缀无运行时开销(无额外分配语义变化)。
  • 风险点仅为「替换不完整」或「误伤其他目录」,通过目录限定 + 替换后计数校验(mysqldao 109 / redisdao 31 / 残留 dao. 为 0)来兜底。

实现要点(防回归)

  • 替换模式必须锚定完整串 global.Tracer.Start(ctx, "dao.,避免误改 mysqldao./redisdao. 之外的其它 dao 文本(如注释、错误信息)。
  • 严格限定目录:internal/mysqldao/*.go 与 internal/redisdao/*.go,不要对仓库根或 internal/ 整体执行替换(会误伤 internal/service 中可能存在的同名串)。
  • 替换后必须核验:internal/mysqldao 与 internal/redisdao 中 "dao. 残留为 0;"mysqldao. 计数 109、"redisdao. 计数 31(与替换前一致)。
  • 未发现任何测试或断言依赖 span 名字符串,改名不会破坏断言;仍以 go build ./... + go vet ./... 作为回归基线。
  • 不改动 configs/config.yaml(第 2 行 Domain: * 为非法 YAML,属用户本地配置,本次不处理)。

架构设计

调用链与 span 命名分层(本次改动仅涉及最下两层的命名):

flowchart TD
    A["routers/api/v1 handler<br/>Gin 中间件 server span"] --> B["internal/service<br/>span: service.Xxx"]
    B --> C["internal/mysqldao<br/>span: mysqldao.Xxx(本次由 dao. 改名)"]
    B --> D["internal/redisdao<br/>span: redisdao.Xxx(本次由 dao. 改名)"]
    C --> E[("MySQL")]
    D --> F[("Redis")]

目录结构

internal/mysqldao/
├── quota.go                  # [MODIFY] 18 处 span 前缀 dao. → mysqldao.
├── outfit.go                 # [MODIFY] 13 处
├── order.go                  # [MODIFY] 12 处
├── clothes.go                # [MODIFY] 9 处
├── closet.go                 # [MODIFY] 8 处
├── user.go                   # [MODIFY] 7 处
├── horoscope.go              # [MODIFY] 7 处
├── benefit_grant_task.go     # [MODIFY] 7 处
├── collect.go                # [MODIFY] 6 处
├── like.go                   # [MODIFY] 6 处
├── notification.go           # [MODIFY] 6 处
├── auditlog.go               # [MODIFY] 4 处
├── goods.go                  # [MODIFY] 3 处
└── vipflowlog.go             # [MODIFY] 3 处
internal/redisdao/
├── quota.go                  # [MODIFY] 6 处 span 前缀 dao. → redisdao.
├── collect.go                # [MODIFY] 4 处
├── like.go                   # [MODIFY] 4 处
├── auth.go                   # [MODIFY] 4 处
├── notification.go           # [MODIFY] 4 处
├── user.go                   # [MODIFY] 3 处
├── horoscope.go              # [MODIFY] 2 处
├── lock.go                   # [MODIFY] 2 处
├── outfit.go                 # [MODIFY] 1 处
└── closet.go                 # [MODIFY] 1 处
README.md                     # [MODIFY] 可选:目录树中 mysqldao/redisdao 说明补 span 命名约定(mysqldao.* / redisdao.*)

Agent Extensions

SubAgent

  • code-explorer
  • Purpose:替换完成后复核两个 DAO 目录的 span 命名:确认 internal/mysqldao 全部为 mysqldao. 前缀、internal/redisdao 全部为 redisdao. 前缀、无 "dao. 残留,且 internal/service、pkg/upload、pkg/tokenhub 的 span 名未被误改
  • Expected outcome:输出各目录前缀计数与残留清单,确保 140 处全部正确改名、零误伤