1
0
Files
nex/openspec/specs/module-logging/spec.md
lanyuanxiaoyao 280099b89c refactor: 后端日志系统重构
- 新增模块化日志器(pkg/logger/module.go)
- 新增 GORM 日志适配器
- 统一日志入口,移除所有 zap.L() 全局 logger 调用
- 字段标准化
- 启动阶段使用结构化日志
- 更新所有相关测试
2026-04-23 18:37:51 +08:00

4.4 KiB
Raw Blame History

Module Logging

Purpose

定义模块化日志器规范,支持模块标识和 Context 传播,实现日志来源快速定位和请求追踪链完整性。

Requirements

Requirement: 模块标识注入

系统 SHALL 支持通过构造函数注入带模块标识的 logger。

Scenario: 构造函数注入模块 logger

  • WHEN 创建需要记录日志的组件
  • THEN 构造函数 SHALL 接受 *zap.Logger 参数
  • THEN SHALL 使用 logger.Named("module.name") 绑定模块标识
  • THEN SHALL 将 logger 存储在结构体字段中

Scenario: 模块标识格式

  • WHEN 绑定模块标识
  • THEN 单一职责包 SHALL 使用包名(如 database
  • THEN 多实体包 SHALL 使用 包名.实体名(如 handler.proxy
  • THEN 子包 SHALL 使用 包名.子包名(如 handler.middleware

Scenario: 模块标识输出

  • WHEN 记录日志
  • THEN Console 格式 SHALL 输出为 [module.name]
  • THEN JSON 格式 SHALL 包含 "logger":"module.name" 字段

Requirement: 禁止全局 logger

系统 SHALL 禁止在业务代码中使用全局 logger。

Scenario: 移除 zap.L() 调用

  • WHEN 重构现有代码
  • THEN SHALL 移除所有 zap.L() 调用
  • THEN SHALL 通过构造函数注入 logger
  • THEN 允许仅在测试代码中使用 zap.L()zap.NewNop()

Scenario: 移除 zap.L() fallback

  • WHEN 构造函数 logger 参数为 nil
  • THEN SHALL NOT 使用 zap.L() 作为默认值
  • THEN 调用方 SHALL 必须传入有效的 logger

Requirement: Request ID 传播

系统 SHALL 通过 Context 传播 request_id。

Scenario: Context 注入 request_id

  • WHEN 中间件生成 request_id
  • THEN SHALL 存储到 context.Context
  • THEN SHALL 使用类型安全的 context key

Scenario: 从 Context 提取 request_id

  • WHEN 业务层需要记录日志
  • THEN SHALL 从 gin.Context 提取 request_id
  • THEN SHALL 使用 logger.With(zap.String("request_id", id)) 创建带 request_id 的 logger
  • THEN 日志 SHALL 自动包含 request_id 字段

Scenario: Request ID 辅助函数

  • WHEN 使用 request_id
  • THEN pkg/logger SHALL 提供 RequestIDFromContext(ctx) 辅助函数
  • THEN 辅助函数 SHALL 返回 zap.Field 类型

Requirement: 单行输出

系统 SHALL 保证所有日志单行输出。

Scenario: Console 单行输出

  • WHEN 记录日志到 stdout
  • THEN SHALL 单行输出
  • THEN 字段之间 SHALL 使用空格分隔

Scenario: JSON 单行输出

  • WHEN 记录日志到文件
  • THEN SHALL 单行紧凑输出
  • THEN SHALL NOT 使用美化缩进

Scenario: 多行数据保留

  • WHEN 日志数据本身包含多行如堆栈跟踪、SQL 换行)
  • THEN SHALL 保留原始多行格式

Requirement: 模块命名规范

系统 SHALL 遵循模块命名规范。

Scenario: Handler 层命名

  • WHEN 创建 handler 层 logger
  • THEN ProxyHandler SHALL 使用 handler.proxy
  • THEN ProviderHandler SHALL 使用 handler.provider
  • THEN ModelHandler SHALL 使用 handler.model
  • THEN StatsHandler SHALL 使用 handler.stats
  • THEN Middleware SHALL 使用 handler.middleware

Scenario: Provider 层命名

  • WHEN 创建 provider 层 logger
  • THEN Client SHALL 使用 provider.client

Scenario: Conversion 层命名

  • WHEN 创建 conversion 层 logger
  • THEN Engine SHALL 使用 conversion.engine
  • THEN OpenAI Adapter SHALL 使用 conversion.openai
  • THEN Anthropic Adapter SHALL 使用 conversion.anthropic

Scenario: Service 层命名

  • WHEN 创建 service 层 logger
  • THEN RoutingCache SHALL 使用 service.routing_cache
  • THEN StatsBuffer SHALL 使用 service.stats_buffer
  • THEN ProviderService SHALL 使用 service.provider
  • THEN ModelService SHALL 使用 service.model
  • THEN RoutingService SHALL 使用 service.routing
  • THEN StatsService SHALL 使用 service.stats

Scenario: Repository 层命名

  • WHEN 创建 repository 层 logger
  • THEN ProviderRepository SHALL 使用 repository.provider
  • THEN ModelRepository SHALL 使用 repository.model
  • THEN StatsRepository SHALL 使用 repository.stats

Scenario: Infrastructure 层命名

  • WHEN 创建基础设施层 logger
  • THEN Database SHALL 使用 database
  • THEN Config SHALL 使用 config