Files
backend/.qoder/repowiki/zh/content/配置管理/日志配置.md
lan a4b6c5011e
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
chore(git): 更新.gitignore以忽略新的本地文件
2025-11-30 08:33:17 +08:00

367 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 日志配置
<cite>
**本文引用的文件**
- [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)
</cite>
## 目录
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["配置加载<br/>pkg/config/config.go"] --> B["日志工厂<br/>pkg/logger/logger.go"]
B --> C["全局管理器<br/>pkg/logger/manager.go"]
C --> D["中间件使用<br/>internal/middleware/logger.go"]
C --> E["恢复中间件<br/>internal/middleware/recovery.go"]
C --> F["应用入口初始化<br/>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 "应用入口<br/>cmd/server/main.go"
participant Cfg as "配置加载<br/>pkg/config/config.go"
participant LMgr as "日志管理器<br/>pkg/logger/manager.go"
participant LNew as "日志工厂<br/>pkg/logger/logger.go"
participant MW as "中间件<br/>internal/middleware/logger.go"
participant Rec as "恢复中间件<br/>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_sizeMB时触发轮转。
- 最多保留 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)