# 日志配置 **本文引用的文件** - [cmd/server/main.go](file://cmd/server/main.go) - [pkg/config/config.go](file://pkg/config/config.go) - [pkg/logger/logger.go](file://pkg/logger/logger.go) - [pkg/logger/manager.go](file://pkg/logger/manager.go) - [internal/middleware/logger.go](file://internal/middleware/logger.go) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go) - [go.mod](file://go.mod) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向 CarrotSkin 项目的开发者与运维人员,系统性说明日志系统的配置与使用方式。重点围绕以下配置项展开:log.level、format、output、max_size、max_backups、max_age 和 compress;并结合 LogConfig 结构体与实际代码实现,给出不同日志级别选择策略、JSON 格式与文本格式的适用场景、以及基于大小与天数的日志轮转工作机制。最后提供生产环境监控集成建议与最佳实践。 ## 项目结构 日志系统由“配置加载层”“日志工厂层”“全局管理器层”“中间件与业务使用层”四部分组成: - 配置加载层:从环境变量加载并解析为 Config,其中包含 LogConfig 字段。 - 日志工厂层:根据 LogConfig 构建 zap.Logger。 - 全局管理器层:提供 Init、GetLogger、MustGetLogger 等接口,确保单例与线程安全。 - 中间件与业务使用层:通过中间件注入日志实例,统一记录 HTTP 请求与异常恢复。 ```mermaid graph TB A["配置加载
pkg/config/config.go"] --> B["日志工厂
pkg/logger/logger.go"] B --> C["全局管理器
pkg/logger/manager.go"] C --> D["中间件使用
internal/middleware/logger.go"] C --> E["恢复中间件
internal/middleware/recovery.go"] C --> F["应用入口初始化
cmd/server/main.go"] ``` 图表来源 - [pkg/config/config.go](file://pkg/config/config.go#L1-L305) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L1-L69) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L1-L51) - [internal/middleware/logger.go](file://internal/middleware/logger.go#L1-L40) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L1-L30) - [cmd/server/main.go](file://cmd/server/main.go#L1-L124) 章节来源 - [pkg/config/config.go](file://pkg/config/config.go#L1-L305) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L1-L69) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L1-L51) - [cmd/server/main.go](file://cmd/server/main.go#L1-L124) ## 核心组件 - LogConfig 结构体:定义日志系统的核心配置项,来源于环境变量映射。 - New:根据 LogConfig 构建 zap.Logger,支持 JSON/Console 编码器、stdout 或文件输出。 - Init/GetLogger/MustGetLogger:全局单例管理,保证线程安全与幂等初始化。 - 中间件 Logger/Recovery:在请求处理前后记录日志,并在 panic 时记录堆栈与上下文。 章节来源 - [pkg/config/config.go](file://pkg/config/config.go#L79-L88) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L1-L69) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L1-L51) - [internal/middleware/logger.go](file://internal/middleware/logger.go#L1-L40) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L1-L30) ## 架构总览 下图展示了从配置到日志输出的关键流程:应用启动时加载配置,初始化日志管理器,随后中间件与业务代码通过全局日志实例进行记录。 ```mermaid sequenceDiagram participant App as "应用入口
cmd/server/main.go" participant Cfg as "配置加载
pkg/config/config.go" participant LMgr as "日志管理器
pkg/logger/manager.go" participant LNew as "日志工厂
pkg/logger/logger.go" participant MW as "中间件
internal/middleware/logger.go" participant Rec as "恢复中间件
internal/middleware/recovery.go" App->>Cfg : 加载配置 Cfg-->>App : 返回 Config(LogConfig) App->>LMgr : Init(LogConfig) LMgr->>LNew : New(LogConfig) LNew-->>LMgr : 返回 zap.Logger LMgr-->>App : 初始化完成 App->>MW : 注入日志实例 App->>Rec : 注入日志实例 MW-->>App : 记录请求日志 Rec-->>App : 记录 panic 与堆栈 ``` 图表来源 - [cmd/server/main.go](file://cmd/server/main.go#L27-L40) - [pkg/config/config.go](file://pkg/config/config.go#L108-L133) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L20-L29) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L14-L68) - [internal/middleware/logger.go](file://internal/middleware/logger.go#L10-L39) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L11-L29) ## 详细组件分析 ### 配置项详解与选择策略 - log.level - 取值范围:debug、info、warn、error,默认 info。 - 选择策略: - 开发/调试:debug,便于定位问题。 - 生产:info,平衡可观测性与性能;仅在需要深入排查时临时提升到 debug。 - 严重问题:error,聚焦错误事件,避免过多噪声。 - log.format - 取值:console、json。 - 适用场景: - console:本地开发终端阅读友好,便于快速定位。 - json:便于日志收集与结构化分析,适合生产与集中化监控。 - log.output - 取值:空/“stdout”表示输出到标准输出;其他路径将自动创建目录并写入文件。 - 适用场景: - 容器化部署:stdout,配合容器日志采集。 - 传统部署:文件路径,结合日志轮转策略。 - log.max_size、log.max_backups、log.max_age、log.compress - 作用:控制日志轮转策略(按大小与天数)与压缩开关。 - 工作机制(基于大小与天数): - 当单个日志文件达到 max_size(MB)时触发轮转。 - 最多保留 max_backups 个历史备份文件。 - 历史文件保留不超过 max_age(天)。 - compress=true 时对旧文件进行压缩,节省磁盘空间。 - 注意:当前代码实现中并未直接使用上述字段进行轮转配置,而是采用文件输出与基础写入同步。若需启用基于大小/天数的轮转,可在日志工厂中引入外部轮转库(如 lumberjack)并传入上述参数。 章节来源 - [pkg/config/config.go](file://pkg/config/config.go#L79-L88) - [pkg/config/config.go](file://pkg/config/config.go#L170-L178) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L43-L60) ### 日志级别选择策略 - debug:用于开发阶段的详细追踪,包含大量上下文信息。 - info:生产环境默认级别,记录关键业务事件与系统状态。 - warn:潜在问题或异常流程,需关注但不影响整体运行。 - error:错误事件,必须处理与上报。 章节来源 - [pkg/logger/logger.go](file://pkg/logger/logger.go#L16-L28) ### JSON 格式与文本格式的适用场景 - JSON: - 优点:结构化强,便于日志聚合、检索与告警。 - 适用:生产环境、集中化日志平台(如 ELK、Loki、Cloud Logging)。 - Console: - 优点:人类可读性强,适合本地开发与快速排障。 - 适用:本地调试、临时诊断。 章节来源 - [pkg/logger/logger.go](file://pkg/logger/logger.go#L30-L41) ### 日志轮转策略(基于大小与天数) - 当前实现要点: - 输出到文件时会自动创建目录并追加写入。 - 未显式配置基于大小/天数的轮转。 - 建议扩展方案: - 引入外部轮转库(如 lumberjack),在 New 中根据 max_size、max_backups、max_age、compress 进行轮转配置。 - 将轮转配置作为可选参数传入,保持现有接口兼容。 章节来源 - [pkg/logger/logger.go](file://pkg/logger/logger.go#L43-L60) - [pkg/config/config.go](file://pkg/config/config.go#L79-L88) ### 日志工厂与全局管理器 - New:根据 LogConfig 构建 zap.Logger,设置级别、编码器与输出目标。 - Init/GetLogger/MustGetLogger:提供线程安全的单例初始化与获取能力,避免重复初始化。 ```mermaid classDiagram class LogConfig { +string level +string format +string output +int max_size +int max_backups +int max_age +bool compress } class LoggerFactory { +New(cfg LogConfig) *zap.Logger } class LogManager { +Init(cfg LogConfig) error +GetLogger() (*zap.Logger, error) +MustGetLogger() *zap.Logger } LogConfig --> LoggerFactory : "输入" LoggerFactory --> LogManager : "被调用" ``` 图表来源 - [pkg/config/config.go](file://pkg/config/config.go#L79-L88) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L14-L68) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L20-L46) 章节来源 - [pkg/logger/logger.go](file://pkg/logger/logger.go#L14-L68) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L1-L51) ### 中间件与业务使用 - Logger 中间件:记录每次 HTTP 请求的方法、路径、状态码、耗时、客户端 IP、User-Agent 等。 - Recovery 中间件:捕获 panic 并记录错误、路径、方法、IP 与完整堆栈,返回统一错误响应。 ```mermaid sequenceDiagram participant Client as "客户端" participant Router as "Gin 路由" participant MW as "日志中间件" participant Handler as "业务处理器" participant Rec as "恢复中间件" Client->>Router : 发起请求 Router->>MW : 进入日志中间件 MW->>MW : 记录请求开始时间与上下文 MW->>Handler : 继续处理 Handler-->>MW : 返回响应 MW->>MW : 记录状态码、耗时、IP、UA MW-->>Router : 返回响应 Note over MW : 若发生 panic,由恢复中间件接管 Router->>Rec : 进入恢复中间件 Rec->>Rec : 记录错误与堆栈 Rec-->>Client : 返回 500 错误 ``` 图表来源 - [internal/middleware/logger.go](file://internal/middleware/logger.go#L10-L39) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L11-L29) - [cmd/server/main.go](file://cmd/server/main.go#L81-L90) 章节来源 - [internal/middleware/logger.go](file://internal/middleware/logger.go#L1-L40) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L1-L30) - [cmd/server/main.go](file://cmd/server/main.go#L81-L90) ## 依赖关系分析 - 外部依赖:zap 用于高性能日志记录;viper 用于配置加载;godotenv 用于 .env 支持。 - 内部依赖:配置模块提供 LogConfig;日志模块提供 Init/GetLogger;中间件依赖日志实例。 ```mermaid graph LR subgraph "外部依赖" Z["go.uber.org/zap"] V["github.com/spf13/viper"] D["github.com/joho/godotenv"] end subgraph "内部模块" CFG["pkg/config/config.go"] LOGF["pkg/logger/logger.go"] LOGM["pkg/logger/manager.go"] MWL["internal/middleware/logger.go"] MWR["internal/middleware/recovery.go"] MAIN["cmd/server/main.go"] end V --> CFG D --> CFG CFG --> LOGM LOGM --> LOGF MAIN --> LOGM MAIN --> MWL MAIN --> MWR Z --> LOGF Z --> MWL Z --> MWR ``` 图表来源 - [go.mod](file://go.mod#L7-L22) - [pkg/config/config.go](file://pkg/config/config.go#L1-L305) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L1-L69) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L1-L51) - [internal/middleware/logger.go](file://internal/middleware/logger.go#L1-L40) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L1-L30) - [cmd/server/main.go](file://cmd/server/main.go#L1-L124) 章节来源 - [go.mod](file://go.mod#L7-L22) - [pkg/config/config.go](file://pkg/config/config.go#L1-L305) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L1-L69) - [pkg/logger/manager.go](file://pkg/logger/manager.go#L1-L51) - [internal/middleware/logger.go](file://internal/middleware/logger.go#L1-L40) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L1-L30) - [cmd/server/main.go](file://cmd/server/main.go#L1-L124) ## 性能考量 - 使用 zap:具备高性能与零分配特性,适合高并发场景。 - 选择合适的日志级别:生产环境默认 info,避免 debug 的额外开销。 - 输出目标选择:stdout 便于容器日志采集;文件输出需注意磁盘 IO 与轮转策略。 - 压缩与保留策略:合理设置 max_size、max_backups、max_age 与 compress,平衡磁盘占用与检索效率。 ## 故障排查指南 - 未初始化日志即使用: - 现象:调用 GetLogger 返回错误提示“日志未初始化,请先调用 logger.Init()”。 - 排查:确认应用入口是否在启动时调用了 logger.Init(cfg.Log)。 - 输出到文件失败: - 现象:初始化日志时报错,无法打开文件。 - 排查:检查 log.output 指定路径是否存在写权限,目录是否可创建。 - panic 未记录: - 现象:服务崩溃但无日志记录。 - 排查:确认已注册 Recovery 中间件并注入了日志实例。 - 日志轮转未生效: - 现象:日志文件持续增大。 - 排查:当前实现未使用 max_size/max_backups/max_age/compress 进行轮转,需扩展轮转逻辑。 章节来源 - [pkg/logger/manager.go](file://pkg/logger/manager.go#L31-L37) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L43-L60) - [internal/middleware/recovery.go](file://internal/middleware/recovery.go#L11-L29) - [cmd/server/main.go](file://cmd/server/main.go#L81-L90) ## 结论 - CarrotSkin 的日志系统以 zap 为核心,通过配置驱动实现灵活的日志级别、编码器与输出目标切换。 - 当前未直接启用基于大小/天数的轮转,建议在日志工厂中引入轮转库并使用 LogConfig 的 max_size、max_backups、max_age、compress 字段。 - 在生产环境中推荐使用 JSON 格式与 stdout 输出,结合集中化日志平台与告警策略,提升可观测性与可维护性。 ## 附录 ### 配置项一览与默认值 - log.level:默认 info - log.format:默认 json - log.output:默认 logs/app.log(文件输出) - log.max_size:默认 100 MB - log.max_backups:默认 3 - log.max_age:默认 28 天 - log.compress:默认 true 章节来源 - [pkg/config/config.go](file://pkg/config/config.go#L170-L178) ### 环境变量映射 - LOG_LEVEL → log.level - LOG_FORMAT → log.format - LOG_OUTPUT → log.output 章节来源 - [pkg/config/config.go](file://pkg/config/config.go#L224-L228) ### 配置示例与最佳实践 - 示例一:本地开发(控制台输出,便于阅读) - LOG_LEVEL=debug - LOG_FORMAT=console - LOG_OUTPUT=stdout - 示例二:生产(结构化日志,集中化采集) - LOG_LEVEL=info - LOG_FORMAT=json - LOG_OUTPUT=stdout - 示例三:传统服务器(文件输出,配合轮转) - LOG_LEVEL=info - LOG_FORMAT=json - LOG_OUTPUT=/var/log/carrotskin/app.log - max_size=100 - max_backups=3 - max_age=28 - compress=true - 最佳实践: - 生产环境统一使用 JSON 格式与 stdout,便于容器日志采集。 - 严格控制日志级别,避免 debug 在生产长期开启。 - 对关键路径增加结构化字段(如用户 ID、请求 ID),便于关联追踪。 - 在中间件中统一记录请求上下文,确保异常时具备足够信息。 - 如需文件轮转,建议在日志工厂中引入轮转库并使用上述配置项。 章节来源 - [pkg/config/config.go](file://pkg/config/config.go#L170-L178) - [pkg/logger/logger.go](file://pkg/logger/logger.go#L30-L41) - [internal/middleware/logger.go](file://internal/middleware/logger.go#L30-L37)