6.9 KiB
6.9 KiB
name, overview, todos
| name | overview | todos | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 按层区分 DAO span 命名 | 将 mysqldao 的 span 名由 dao.X 改为 mysqldao.X、redisdao 的改为 redisdao.X,共 140 处,解决两层 span 名无法区分的问题。 |
|
产品概述
统一调整 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/ 两个目录。
关键决策与取舍:
- 前缀命名用
mysqldao./redisdao.而非mysql./redis.:与包名(package mysqldao/package redisdao)完全一致,Go 项目中 span 名即包名+方法名,排查时可从 span 名直接定位到文件与包,无需映射记忆。 - 批量 sed 而非逐处手改:140 处手工改必漏;用
sed -i 's/Tracer\.Start(ctx, "dao\./Tracer.Start(ctx, "mysqldao./g'这类按目录执行的命令可保证一致性与完整性,且模式串锚定了Tracer.Start(ctx, "dao.全串,不会误伤字符串变量、注释或日志中的dao.。 - 只改前缀,不改方法名:方法名与所在函数名一一对应,改名会造成与函数名不一致的二次困惑;同时避免破坏任何按名称检索的既有习惯。
- 不引入常量:项目其余前缀(
service.、upload.、scheduler.)均为字面量,沿用字面量保持风格统一,不引入新的抽象层(YAGNI)。 - 不改动 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 处全部正确改名、零误伤