Grafana Tempo 的 Agent 协作开发规范:AGENTS.md 全解析与贡献实战指南
2026/9/18 5:56:44 网站建设 项目流程

Grafana Tempo 的 Agent 协作开发规范:AGENTS.md 全解析与贡献实战指南

【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo

Grafana Tempo 是一个面向高吞吐、低依赖场景的分布式链路追踪后端,其代码仓库根目录下的 AGENTS.md 是一份面向 AI Agent(Cursor、Claude Code、Copilot 等)与人类开发者的统一协作指南。它定义了 Changelog 管理、编码规范、代码审查、文档写作和提交前检查五大约束。本文以该文件为核心骨架,结合.agents/guidance/下的详细规范、Makefile 中的命令体系以及 .chloggen/ 的变更条目机制,逐层拆解 Tempo 仓库对代码贡献的硬性要求,帮助你(或你的 Agent)在提交 PR 前一次通过评审。

一、AGENTS.md 在仓库中的定位

AGENTS.md 位于仓库根目录,是 Tempo 面向 AI 编程工具与人工贡献者的"第一入口"。它本身只有五个小节、二十余行,但每一条都是一份更详细规范的入口指针:

小节职责指向的详细规范
Changelog Entries管理用户可见变更的 changelog 条目.chloggen/README.md
Coding Standards编写/修改 Go 代码前的编码标准.agents/guidance/coding.md
Code Review Standards进行代码审查时的多领域审查框架.agents/guidance/code-review.md
Writing Standards撰写 Markdown 文案时的写作标准.agents/guidance/writing.md
Pre-Commit Checklist推送或开 PR 前的自检清单.agents/guidance/precommit.md

从设计意图看,Tempo 将"规则"与"入口"分离:AGENTS.md 保持极简,保证任何 Agent 在打开仓库时能快速定位应遵守的规范;详细内容下沉到.agents/guidance/,避免根文档臃肿。这种模式本身即是值得借鉴的仓库治理实践。

二、Changelog Entries:用 chloggen 替代直接编辑 CHANGELOG.md

AGENTS.md 的第一条硬性规则是:永远不要直接编辑CHANGELOG.md。每个用户可见的变更都必须在 .chloggen/ 下新增一个 YAML 条目。

2.1 为什么禁止直接编辑

Tempo 使用仓库内置的 chloggen 工具管理变更日志。直接在共享的CHANGELOG.md上并发编辑必然产生合并冲突;改为每个 PR 携带独立的小 YAML 文件后,冲突被彻底消除,发布时再由工具统一汇总(collate)进 changelog。这正是 .chloggen/README.md 中说明的机制。

2.2 创建与校验命令

从 Makefile 可以看到 chloggen 从 tools 子模块构建,并以仓库根目录为工作目录运行:

make chlog-new # 生成 .chloggen/<当前分支名>.yaml(基于 TEMPLATE.yaml) make chlog-new FILENAME=my-change # 显式指定条目文件名(main/master 或 detached HEAD 下必须指定) make chlog-validate # 校验所有待发布条目 make chlog-preview # 将待发布条目渲染到标准输出预览

发布(仅维护者)时执行:

make chlog-update VERSION=v2.11.0 # 汇总条目写入 CHANGELOG.md 并删除条目文件

2.3 条目文件的结构

生成的条目基于 TEMPLATE.yaml(模板文件本身在.chloggen/目录中),填写示例:

change_type: enhancement # breaking | change | feature | enhancement | bug_fix | security component: metrics-generator # 必须在 config.yaml 的 components 允许清单内 note: A brief description of the change. issues: [] # 可选;留空则发布时自动从提交信息解析 PR 号 subtext: # 可选补充细节 user: your-github-handle # 渲染为 "(@your-github-handle)"

change_type关键字在 changelog 中对应不同分区(breaking→🛑、change→🔧、feature→🚀、enhancement→💡、bug_fix→🧰、security→🔒)。component必须落在 .chloggen/config.yaml 的允许清单内,否则chlog-validate直接拒绝;新增组件需在同一次 PR 中同步修改该清单。

2.4 写 note 的核心原则

  • 保持简短,最多一两句话,聚焦用户影响
  • 描述"用户得到了什么",而非"技术上做了什么";
  • 例如:✅Improve read performance by pushing down predicates to the parquet iterators.;❌Add support for pushdown predicates in the parquet iterators.
  • 确需补充的实现细节放在subtext,不放 note。

这一条规则直接呼应了 docs 侧对 changelog 质量的长期要求:变更日志是面向运维与终端用户的,不是内部实现的流水账。

三、Coding Standards:Go 编码规范的五个层次

.agents/guidance/coding.md 从核心哲学、测试、错误处理、并发、资源管理、惯用模式、性能到 Tempo 特有约定,系统定义了 Go 代码的书写底线。

3.1 核心哲学与测试

  • 写"干净、朴素、惯用"的 Go,标准库优先,显式优于隐式;
  • 测试先行是默认路径:先写测试 → 验证其失败(证明测试确实有效)→ 写最小实现使其通过 → 重构;
  • 测试结构采用 table-driven + subtests 模式(规范中给出了TestSomething的完整骨架示例);
  • 覆盖率目标(作为指导而非硬性规则):关键路径 >80%、业务逻辑 >75%、整体 >70%;
  • 任何新/变更行为都必须覆盖 happy path、错误路径与边界(nil、空、零值)。

3.2 错误处理

  • 一律用fmt.Errorf("...: %w", err)包装错误以保留上下文,禁止直接返回裸错误;
  • 绝不静默吞错:_ = someFunc()属于反面示例;
  • 比较错误用errors.Is/errors.As,禁止err == ErrNotFound(包装后会失效);
  • 生产服务与库代码中禁止 panic,初始化失败应向上返回错误并交给main退出。

3.3 并发与资源管理

  • goroutine 必须有明确生命周期,优先响应ctx.Done()取消信号;
  • 用 channel 做编排/信号,用 mutex 保护共享状态;共享计数器等给出SafeCounter式的显式加锁示例;
  • 必须跑go test -race,发现竞态即修复而非抑制;
  • context 必须是函数第一个参数并贯穿所有 goroutine;
  • 资源获取后立即defer清理(文件、HTTP body、数据库行、锁、连接)。

3.4 性能:先测量再优化

  • 性能优化必须 profile 先行,go test -cpuprofile=cpu.out -memprofile=mem.out -bench=. ./...go test -bench=. -benchmem ./...是标准工具;
  • 热路径上 3 倍慢的实现若能换来清晰度可以接受——上下文比基准数字更重要;
  • 分配模式:已知大小预分配make([]T, 0, n)、紧循环中复用 buffer、短生命周期高频对象用sync.Pool、循环拼接字符串用strings.Builder
  • 算法上优先 O(n log n),对 Parquet 迭代器使用SeekTo()跳过已扫描的 row group。

规范中还给出了 Tempo 的已知热路径清单,这些位置改动必须有基准数据支撑:

路径文件基准佐证
Span 摄取instance.push()modules/ingester/instance.goBenchmarkInstancePushBenchmarkInstanceContention
Live trace 追加liveTrace.Push()modules/ingester/trace.go每 span 在 mutex 下调用
TraceQL 二元运算pkg/traceql/ast_execute.goBenchmarkBinOp
Parquet 行号比较pkg/parquetquery/iters.goBenchmarkEqualRowNumber
Parquet TraceQL 块执行tempodb/encoding/vparquet5/block_traceql.go4 个以上关系运算符基准
字符串驻留(interning)pkg/parquetquery/intern/intern.go对重复值使用 unsafe

3.5 Tempo 特有约定(从代码库中沉淀的惯例)

  • 配置校验返回(warnings []error, err error):warnings 非致命(降级运行),err 致命——参考 modules/overrides 及 config 校验相关实现,让运维在部分配置缺失时仍能启动;
  • 复杂构造函数用类型化 option 接口而非裸func(*T),option 自描述且可携带状态;
  • 租户行为必须透传:通过 handler 链传递overrides.Interface,始终从 context 提取 tenant ID,绝不硬编码租户级行为;
  • 泛型用于类型安全队列/容器(如PriorityQueue[T Op]),消除运行时类型断言;
  • 队列组件内嵌 Prometheus gauge,并为测试场景做 nil 保护;
  • mock 用_占位未用参数、//nolint:all抑制 stub 的 lint、线程安全计数器做断言
  • 同一初始化逻辑重复 3 次以上提取为局部闭包
  • 新增查询路径保持向后兼容:旧路径保留,新路径由 hint/flag 门控,引擎选择走哪条路,调用方不变;
  • 配置默认值与破坏性变更:在CHANGELOG.md与变更点代码注释中同步说明,移除配置字段时留下替代说明(如QueryIngestersUntil在 v2.7 移除,改用QueryBackendAfter)。

四、Code Review Standards:十遍通过的审查框架

.agents/guidance/code-review.md 定义了多领域审查框架,要求按 pass 系统推进,并为每个发现记录:what、why、where(file:line)、severity 和具体修复方案。

4.1 严重级别与路由

  • CRITICAL:可利用漏洞、数据丢失、崩溃(注入、认证绕过、热路径 nil 解引用、硬编码凭据);
  • HIGH:严重 bug、破坏性行为、安全弱点(关键路径缺错误处理、竞态、资源/goroutine 泄漏、弱加密、破坏性 API 变更);
  • MEDIUM:质量问题、潜在 bug、非惯用代码(缺校验、N+1 查询、缺缓存);
  • LOW:风格、小改进、文档(注释错别字、命名建议)。

路由规则:任何 CRITICAL/HIGH 必须修复后才能合并,并考虑重审设计;仅 MEDIUM/LOW 则定点修复、不阻塞。

4.2 十个审查 Pass

  1. Security:OWASP Top 10、硬编码凭据、注入;特别强调——配置结构中任何命名含password/token/key/secret/credential/auth的字段必须使用flagext.Secretconfig.Secret(来自github.com/prometheus/common/config),确保日志与序列化输出中被脱敏;并给出 grep 排查命令集(os/exec、弱密码学crypto/md5/crypto/sha1math/rand用于安全目的等);
  2. Bug Diagnosis:nil 解引用、数据竞态、off-by-one、资源未关闭、未检查的类型断言;
  3. Error Handling:忽略错误、静默吞错、缺少%w包装上下文、panic 代替错误返回;
  4. Code Quality & Logic:逻辑错误、边界缺失、跨文件一致性、死代码、测试覆盖缺口;
  5. Performance:O(n²) 算法、紧循环内分配、热路径回归必须有基准佐证(已知热路径同 coding.md 清单);
  6. Go Idioms:stuttering 命名、接口过大、无生命周期 goroutine、==比较错误、循环内 defer、init()滥用;
  7. Architecture & Design:紧耦合、缺抽象、违反单一职责、循环依赖、阻碍可测试性的全局状态;
  8. Documentation:示例无法编译或与 API 不符、导出符号缺注释、README 命令失效;
  9. Comment Accuracy:过期/误导性注释、错误的参数/返回值描述、未解决的 TODO/FIXME(给出git diff HEAD --name-only | xargs grep -n "TODO\|FIXME\|HACK\|XXX"排查命令);
  10. Reference Integrity:注释中引用的 spec/设计文档必须真实存在、且代码与所引章节描述一致。

输出格式要求按Critical Issues (Must Fix)High Priority IssuesMedium Priority IssuesLow Priority IssuesSummary(含各级数量与 MUST FIX / TARGETED FIXES / READY 结论)组织。

4.3 Tempo 维护者的实战审查标准

  • 测试特异性:锁定完整行为契约而非松散断言,如用assert.Equal(t, "GET /api/users/<_>", result)而非assert.Contains(t, result, "<_>")
  • 并发假设必须显式:跨 goroutine 共享的切片/指针要注明是否安全,必要时解释拷贝原因;
  • 性能声明需要生产证据:仅微基准不足以定论,须用真实/仿真集群 profile 佐证(引述维护者原话:"SortTrace is not present in CPU profiles at all... 0.02% of CPU");
  • 异步行为必须文档化:Tempo 在 live-store、block-builders 等多处异步执行限额,代码注释与文档都必须明确说明;
  • 最小化导出:默认不导出,仅在测试中使用的保持在测试文件内且不导出;
  • 进程内调用不过度设计:monolith 场景直接函数调用即可,避免 gRPC/channel/worker pool;
  • 命名必须精确:一个"canonical"命名的争议最终被解析为NormalizeQuery——名字应传达无歧义的意图。

五、Writing Standards:Markdown 语义化换行(SemBr)

.agents/guidance/writing.md 要求所有文档、README、设计文档与 Agent 指南采用Semantic Line Breaks(SemBr)写作:在语义边界换行,而不是固定列宽硬折或整段一行。Tempo 仓库的 docs/ 与各模块 AGENTS.md 普遍遵循这一约定。

  • 原因:diff 只显示真正变更的句子/子句;审查者可针对单句评论;LLM 辅助写作倾向产出长而密的段落,SemBr 让这类编辑保持可审;
  • 工具:官方 SemBr 技能位于 .agents/doc-agents/ 工作流体系内(skill 定义在.claude/skills/sembr-reformat/SKILL.md,源自 MIT 许可的 sembr/skills 项目);
  • 范围:只对新增文案与正在编辑的段落应用;不批量重排未触及文件(避免 diff 噪音);代码块、表格、YAML frontmatter 及换行有语法意义的标记一律保留原样。

六、Pre-Commit Checklist:推送前的五道关卡

.agents/guidance/precommit.md 定义了开 PR 前的最低门槛,对应命令均可从 Makefile 找到实现。

6.1 格式化与 Lint

make fmt # gofumpt + goimports;CI 跑 make check-fmt,工作树不干净即失败 make lint # golangci-lint make lint base=origin/main # 仅检查相对 base 分支的 diff(与 CI 行为一致,大仓库推荐)

6.2 单元测试与 E2e

make test # 全包测试 make test-with-cover # 带 race detector 与覆盖率,匹配 CI 拆分 make test-with-cover-pkg # CI 将测试拆为 pkg / tempodb / tempodb-wal / others 四组 make test-with-cover-tempodb make test-with-cover-tempodb-wal make test-with-cover-others make test-e2e # 全套 E2e(需 Docker,先构建本地 Tempo 镜像) make test-e2e-api # 也可单独跑各套件 make test-e2e-operations make test-e2e-limits make test-e2e-metrics-generator make test-e2e-storage make test-e2e-clean # 跑完后清理 Docker 拥有的测试目录

6.3 开 PR 前的最低门槛

  1. make fmt——工作树无 dirty;
  2. make lint base=origin/main——无新增 lint 错误;
  3. make test——全部单元测试通过;
  4. go test -race ./...(或make test-with-cover)——变更包无竞态;
  5. make chlog-validate——用户可见变更存在.chloggen/条目(绝不直接编辑CHANGELOG.md)。

6.4 PR 描述与推送纪律

  • 开 PR 前阅读.github/pull_request_template.md并按模板结构填写;注意非交互工具用gh pr create --body显式传 body 会绕过 GitHub 模板自动填充,需手动应用模板;
  • 已进入评审的 PR 禁止改写历史:用新提交回应评审意见,不 amend/squash/rebase 已评审提交;不 force push(含--force-with-lease,它虽防覆盖他人工作,但仍会重写历史并破坏 GitHub 的 "changes since your last review" 视图);
  • 唯一例外:基于main的 rebase(如解决冲突),且必须单独推送、不夹带其他改动,并在 PR 评论中说明。

七、Agent 工作流的延伸:文档写作管线

AGENTS.md 指向的规范之外,.agents/README.md 还描述了完整的 AI 辅助文档工作流(由 Tempo 维护团队专门为文档写作编排的 agent 体系):

  • PR 驱动/docs-workflow依次执行 triage(/docs-pr-check分类文档状态)→ write(/docs-pr-write补写缺失文档)→ review(/docs-review检查风格/准确性/完整性),每步之间暂停等人工确认;
  • 从零写作:运行 .agents/doc-agents/writers/writer-agent.md,以五阶段交互推进:Teacher(理解功能)→ Information Architect(规划结构)→ Author(起草)→ Reviewer(审查)→ Committer(准备 PR);
  • 共享资源:.agents/doc-agents/ 下的 docs-context-guide(代码-文档映射)、style-guide(Grafana 风格规则)、best-practices(常见陷阱)、verification-checklist(提交前质量清单)等,供 agent 与人类作者共用;
  • 领域知识:编写 metrics-generator 文档时须加载 modules/generator/AGENTS.md 作为额外上下文(覆盖功能范围、配置结构、常见困惑点与 v3 架构变化)。

八、结语:把规范变成可自动执行的流程

AGENTS.md 的价值不在于规则数量,而在于它将 Tempo 仓库的工程纪律编码成了 Agent 可直接读取、直接执行的指令链:changelog 用 chloggen 避免合并冲突,编码与审查规范用可 grep 的命令与代码骨架消除歧义,提交门槛用make目标实现可复现校验。对贡献者而言,遵循这份指南意味着:先跑make chlog-newmake fmt,再写测试与代码,最后按make lint base=origin/main+make test+make chlog-validate的顺序自检——这套流程既能通过 CI,也能大幅缩短维护者评审往返。如果你正在用 AI 工具为 Tempo 或其他大型 Go 仓库做贡献,将 AGENTS.md 及.agents/guidance/中的规范作为首轮上下文加载,是让 Agent 产出符合上游标准的最高效路径。

【免费下载链接】tempoGrafana Tempo is a high volume, minimal dependency distributed tracing backend.项目地址: https://gitcode.com/GitHub_Trending/tempo1/tempo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询