--- tags: [] aliases: - 🏗️ AI 辅助基础设施构建 SOP (v1.0) - [全局日志篇] date created: 星期三, 十二月 10日 2025, 11:50:40 晚上 date modified: 星期三, 十二月 10日 2025, 11:52:08 晚上 --- # 🏗️ AI 辅助基础设施构建 SOP (v1.0) - [全局日志篇] **核心理念:** 1. **Configuration Driven (配置驱动):** 先定义配置结构与 Viper 映射,再实现逻辑。 2. **Zero Allocation Constraint (零分配约束):** 在 Prompt 层面封杀 `zap.Any`,强制使用强类型字段。 3. **Layered Delivery (分层交付):** 先交付 `pkg/log` (Level 0),再交付 `middleware` (Level 1)。 --- ## 📋 准备工作:上下文注入 在使用以下 Prompt 前,请确保 AI 已理解《全局日志模块详细设计说明书》的全部内容。 - `{语言/框架}`: Go 1.24+ / Uber Zap / Lumberjack v2 - `{模块路径}`: `internal/pkg/log` (核心) & `internal/middleware` (集成) - `{关键约束}`: `pkg/log` **严禁依赖** `gin` 或 `viper` (仅接收 Config struct)。 --- ## Phase 0: 依赖隔离与任务拆解 (The Dependency-Aware MECE) **目的:** 防止 AI 在编写日志核心时引入业务层代码(如 Gin),导致循环依赖。 ### 🤖 拆解者 Prompt (复制使用) ```Markdown 你现在是我的 **System Architect (系统架构师)**。 我们要实现 `Global Logging Infrastructure`。基于《详细设计说明书》,请执行 **“依赖隔离任务拆解”**。 **1. 架构红线 (Architecture Rules):** - **Level 0 (Core):** `internal/pkg/log`。只依赖 `zap`, `lumberjack`, standard `context`。**严禁依赖 `gin`**。 - **Level 1 (Integration):** `internal/middleware`。依赖 `internal/pkg/log` 和 `gin`。 **2. 原子化切分:** 请将工作拆解为两个独立的 Batch,每个 Batch 包含若干 Step。 - **Batch A (Core)**: 必须按 `options.go` (配置) -> `zap.go` (构造) -> `context.go` (桥接) -> `log.go` (门面) 的顺序。 - **Batch B (Middleware)**: 包含 `trace.go`, `access_log.go`, `recovery.go`。 **3. 输出格式:** 请输出一个 **Markdown Checklist**。 格式示例: - [ ] **Batch A - Step 1: {文件名}** - {核心职责} (关键设计点: …) … ``` --- ## Phase 0.5: API 签名锁定 (API Surface Lock) **目的:** 在实现 `zap` 复杂构建逻辑前,先锁死对外暴露的“门面”方法,确保调用体验。 ### 🤖 Prompt 0.5: 定义门面接口 ```Markdown 在实现具体逻辑前,让我们先锁定 `internal/pkg/log` 的 **Public API**。 请只输出 `log.go` 和 `context.go` 中 **Exported Functions** 的签名(无需函数体)。 **关键要求:** 1. **初始化:** `Init(opts …Option)` 设计为 Functional Options 模式还是直接传 Struct?(依据设计文档应为 Struct 传入,但保留 Option 扩展性)。 2. **上下文注入:** `WithContext(ctx context.Context) *zap.Logger` 的签名确认。 3. **静态代理:** `Info`, `Error` 等静态方法如何处理 `CallerSkip`?请在注释中说明。 4. **后台任务:** 必须包含 `StartBackgroundTrace(ctx)` 的定义。 请输出带有完整 Go Doc 的接口定义代码块。 ``` --- ## Phase 1: 配置契约定义 (Configuration Contract) **目的:** 只有确定了“怎么配”,才能决定“怎么写”。 ### 🤖 Prompt 1: 定义配置结构与 Schema ```Markdown 你现在是 **DevOps 专家**。 请定义日志模块的配置结构 (`options.go`) 以及对应的 YAML 写法。 **任务:** 1. **Go Struct:** 定义 `Options` 结构体。 - 包含 `Level`, `Format` (json/console), `Filename`, `MaxSize`, `MaxBackups`, `MaxAge`, `Compress`。 - Tag 必须适配 `mapstructure` (Viper 使用)。 2. **Default Value:** 提供一个 `NewOptions()` 函数返回生产环境推荐的默认值 (100MB, 30个文件, JSON 格式)。 3. **YAML Example:** 给出一个 `config.yaml` 的片段示例。 **约束:** - 字段类型必须明确(如 `MaxSize` 是 int 还是 string? 建议 int 单位 MB)。 ``` --- ## Phase 2: 体验验证 (DX Verification) **目的:** 验证开发者在业务代码中打印日志是否顺手,防止过度封装导致 API 臃肿。 ### 🤖 Prompt 2: 伪代码验证 (复制使用) ```Markdown 配置和接口已锁定。请写一段 **Service 层** 的伪代码,展示如何使用该日志库。 **场景验证:** 1. **标准调用:** 在 `UserRegister` 方法中,如何打日志并自动带上 TraceID? 2. **强类型约束:** 展示使用 `zap.String`, `zap.Int` 的写法。**严禁出现 `zap.Any`**。 3. **子 Context:** 在 `go func()` 中如何使用 `StartBackgroundTrace` 保证链路不断? 4. **Error 处理:** 遇到 DB 错误时,如何记录 log 并返回 error? 请展示代码,并自我评价是否符合“低心智负担”原则。 ``` --- ## Phase 3: 核心防御式实现 (Core Defensive Implementation) **核心机制:** 这是一个**循环步骤**。针对 `internal/pkg/log` 的每个文件执行。 ### 🔄 循环动作 A: 生成代码 **[发送 Prompt]:** ```Markdown 我们现在执行 **Batch A - Step {N}**。 **任务目标:** 生成 `{文件名}` (例如 `zap.go`)。 **设计文档引用:** - 引用《设计说明书》中关于 `{章节名}` 的要求。 **代码质量硬性约束 (Hard Constraints):** 1. **Snake Case:** 所有的 JSON Key (包括 TraceID) 必须手动指定为 snake_case (如 `zap.String("trace_id", v)`)。 2. **No Zap Any:** 严禁在核心逻辑中使用 `zap.Any`。如果是 map/struct,必须手动拆解或实现 `zapcore.ObjectMarshaler`。 3. **Safety:** - `writer.go`: Lumberjack 的 `Compress` 必须默认为 true。 - `log.go`: `globalLogger` 必须有 `sync.Once` 保护,且默认初始化为 Console (避免 nil pointer)。 4. **Caller Skip:** 确保静态方法 (log.Info) 和实例方法 (logger.Info) 的 Caller 层级正确,都能定位到业务代码行号。 请生成完整代码。 ``` ### 🔄 循环动作 B: 质量检查锚点 **[发送 Prompt]:** ```Markdown 代码已生成。请进行 **Self-Correction (自我修正)**: 1. 检查是否有 `fmt.Print` 残留? 2. 检查 `log.go` 中的静态方法是否使用了 `WithOptions(zap.AddCallerSkip(1))`?如果没用,业务层行号会报错。 3. 检查是否引入了 `gin` 或其他业务包?(Level 0 严禁依赖)。 确认无误后,存入记忆,继续下一步。 ``` --- ## Phase 4: 中间件集成 (Middleware Integration) **目的:** 只有当核心 Log 库稳定后,才实现 Gin 中间件。 ### 🤖 Prompt 4: 实现链路追踪与访问日志 ```Markdown 现在进入 **Batch B**。我们需要实现 `internal/middleware/trace.go` 和 `access_log.go`。 **任务要求:** 1. **Trace Middleware:** - 从 Request Header (`X-Trace-ID`) 读取,若无则生成 UUID。 - **关键点:** 必须调用 `log.WithTraceID(ctx, id)` 将 ID 注入 Standard Context,再回写到 `c.Request`。 2. **Access Log Middleware:** - 记录 Start Time, End Time, Latency。 - 使用 `log.WithContext(c.Request.Context()).Info(…)` 打印。 - **字段映射:** `method`, `path`, `ip`, `status`, `latency` (ms)。 3. **Recovery Middleware:** - 捕获 Panic。 - 打印包含 Stack Trace 的 JSON Error 日志 (非 Console 文本)。 - 返回 500 响应。 请一次性生成这三个文件的核心逻辑。 ``` --- ## Phase 5: 极限防御测试 (Extreme Defensive Testing) **目的:** 验证并发安全、文件轮转和敏感数据脱敏。 ### 🤖 Prompt 5: 生成红队测试用例 ```Markdown 核心代码已就绪。请为 `pkg/log` 编写单元测试 `log_test.go`。 **请覆盖以下 3 个高危场景 (Test Cases):** 1. **并发竞争 (Race Detection):** - 启动 100 个 Goroutine,同时调用 `log.WithContext(ctx).Info(…)`。 - 断言:`go test -race` 不报错,且 TraceID 不串号。 2. **Caller 准确性验证:** - 编写一个测试辅助函数,解析输出的 JSON,断言 `caller` 字段指向的是测试代码行号,而不是 `log.go` 内部。 3. **敏感数据脱敏 (Mock):** - 模拟打印 `zap.String("password", "123456")`。 - (注意:如果我们在 Zap Core 层没做拦截,这里需要验证是否通过 AI 辅助代码生成时的规范来避免。此处请测试:如果定义了 Masking Hook,密码是否被替换为 `******`)。 - *注:根据设计文档,我们采用“编码规范+AI辅助”策略,故此处测试应侧重于“TraceID 是否在 Log 中正确出现”。* 请输出 Test 代码。 ``` --- ## Phase 6: SRE 验收 (SRE Review) ### 🤖 Prompt 6: 运维视角审查 ```Markdown 切换角色为 **SRE**。请审查生成的日志模块。 **检查清单:** 1. **磁盘爆炸风险:** `Lumberjack` 配置是否真的生效了?(检查 WriteSyncer 的封装)。 2. **性能损耗:** `WithContext` 是否每次都创建了过多的 Zap 对象?(确认是否只是 Shallow Copy)。 3. **索引友好度:** 时间戳是否为 ISO8601 (`2025-12-10T…`)?如果是 Epoch float,ELK 处理会麻烦。 4. **容灾:** 如果 `logs/` 目录不可写(权限问题),程序会 Panic 还是降级输出到 Stdout? 请给出 1-2 个具体的 `TODO` 优化项。 ```