mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-04-17 22:37:27 +00:00
261 lines
6.9 KiB
Markdown
261 lines
6.9 KiB
Markdown
# 日志系统说明
|
||
|
||
本项目使用 Go 标准库的 `log/slog` 实现结构化日志记录。
|
||
|
||
## 📋 功能特性
|
||
|
||
### 1. 标准的文件存储结构
|
||
|
||
- **当前日志文件**: `oneapi.log` - 实时写入的日志文件
|
||
- **归档日志文件**: `oneapi.2024-01-02-153045.log` - 自动轮转后的历史日志
|
||
|
||
### 2. 自动日志轮转
|
||
|
||
日志文件会在以下情况自动轮转:
|
||
|
||
- **按大小轮转**: 当日志文件超过指定大小时(默认 100MB)
|
||
- **启动时日期检查**: 程序启动时如果检测到日志文件是旧日期创建的,会自动轮转
|
||
- **自动清理**: 只保留最近 N 个日志文件(默认 7 个)
|
||
|
||
### 3. 结构化日志
|
||
|
||
所有日志都包含以下结构化字段:
|
||
|
||
```
|
||
time=2024-01-02T15:30:45 level=INFO msg="user logged in" request_id=abc123 user_id=1001
|
||
```
|
||
|
||
### 4. 多种输出格式
|
||
|
||
- **Text 格式** (默认): 人类可读的文本格式
|
||
- **JSON 格式**: 便于日志分析工具解析
|
||
|
||
### 5. 灵活的日志级别
|
||
|
||
支持四个日志级别:
|
||
- `DEBUG`: 调试信息
|
||
- `INFO`: 一般信息
|
||
- `WARN`: 警告信息
|
||
- `ERROR`: 错误信息
|
||
|
||
## ⚙️ 配置方式
|
||
|
||
### 环境变量配置
|
||
|
||
```bash
|
||
# 日志目录(必需,否则只输出到控制台)
|
||
--log-dir=./logs
|
||
|
||
# 日志级别(可选,默认: INFO,DEBUG 模式除外)
|
||
export LOG_LEVEL=DEBUG # 可选值: DEBUG, INFO, WARN, ERROR
|
||
|
||
# 日志格式(可选,默认: text)
|
||
export LOG_FORMAT=json # 可选值: text, json
|
||
|
||
# 单个日志文件最大大小(可选,默认: 100,单位: MB)
|
||
export LOG_MAX_SIZE_MB=200
|
||
|
||
# 保留的日志文件数量(可选,默认: 7)
|
||
export LOG_MAX_FILES=14
|
||
|
||
# 启用调试模式(会自动将日志级别设为 DEBUG)
|
||
export DEBUG=true
|
||
```
|
||
|
||
### 命令行参数
|
||
|
||
```bash
|
||
# 启动时指定日志目录
|
||
./new-api --log-dir=./logs
|
||
|
||
# 如果不指定日志目录,日志只输出到控制台
|
||
./new-api
|
||
```
|
||
|
||
## 📝 使用示例
|
||
|
||
### 基础使用
|
||
|
||
```go
|
||
import (
|
||
"context"
|
||
"github.com/QuantumNous/new-api/logger"
|
||
)
|
||
|
||
// 记录信息日志
|
||
logger.LogInfo(ctx, "user registered successfully")
|
||
|
||
// 记录警告日志
|
||
logger.LogWarn(ctx, "API rate limit approaching")
|
||
|
||
// 记录错误日志
|
||
logger.LogError(ctx, "failed to connect to database")
|
||
|
||
// 记录调试日志(只在 DEBUG 模式下输出)
|
||
logger.LogDebug(ctx, "processing request with params: %v", params)
|
||
|
||
// 记录系统日志(无 context)
|
||
logger.LogSystemInfo("application started")
|
||
logger.LogSystemError("critical system error")
|
||
```
|
||
|
||
### 日志输出示例
|
||
|
||
**Text 格式** (易读格式):
|
||
```
|
||
[INFO] 2024/01/02 - 15:30:45 | SYSTEM | application started
|
||
[INFO] 2024/01/02 - 15:30:46 | abc123 | user registered successfully
|
||
[WARN] 2024/01/02 - 15:30:47 | def456 | API rate limit approaching | remaining=10, limit=100
|
||
[ERROR] 2024/01/02 - 15:30:48 | ghi789 | failed to connect to database | error="connection timeout"
|
||
```
|
||
|
||
格式说明:`[级别] 时间 | 请求ID/组件 | 消息 | 额外属性(如有)`
|
||
|
||
**JSON 格式**:
|
||
```json
|
||
{"time":"2024-01-02 15:30:45","level":"INFO","msg":"application started","request_id":"SYSTEM"}
|
||
{"time":"2024-01-02 15:30:46","level":"INFO","msg":"user registered successfully","request_id":"abc123"}
|
||
{"time":"2024-01-02 15:30:47","level":"WARN","msg":"API rate limit approaching","request_id":"def456"}
|
||
```
|
||
|
||
## 📂 日志文件结构
|
||
|
||
```
|
||
logs/
|
||
├── oneapi.log # 当前活动日志文件
|
||
├── oneapi.2024-01-01-090000.log # 昨天的日志
|
||
├── oneapi.2024-01-01-150000.log # 昨天下午的日志(如果超过大小限制)
|
||
├── oneapi.2023-12-31-090000.log # 更早的日志
|
||
└── ... # 最多保留配置数量的历史文件
|
||
```
|
||
|
||
## 🔄 日志轮转机制
|
||
|
||
### 轮转触发条件
|
||
|
||
1. **文件大小检查**: 每写入 1000 条日志后检查一次文件大小
|
||
2. **启动时日期检查**: 程序启动时检查日志文件的修改日期,如果不是今天则轮转
|
||
3. **自动清理**: 轮转时自动删除超过保留数量的旧日志文件
|
||
|
||
> **注意**: 日志不会在运行时动态检查日期变化。如果需要每天自动轮转日志,建议:
|
||
> - 使用定时任务(如 cron)每天重启服务
|
||
> - 或者配置较小的日志文件大小,让它自动按大小轮转
|
||
|
||
### 轮转流程
|
||
|
||
1. 检测到需要轮转时,关闭当前日志文件
|
||
2. 将 `oneapi.log` 重命名为 `oneapi.YYYY-MM-DD-HHmmss.log`
|
||
3. 创建新的 `oneapi.log` 文件
|
||
4. 异步清理超过数量限制的旧日志文件
|
||
5. 记录轮转事件到新日志文件
|
||
|
||
## 🎯 最佳实践
|
||
|
||
### 1. 生产环境配置
|
||
|
||
```bash
|
||
# 使用 INFO 级别,避免过多调试信息
|
||
export LOG_LEVEL=INFO
|
||
|
||
# 使用 JSON 格式,便于日志分析工具处理
|
||
export LOG_FORMAT=json
|
||
|
||
# 设置合适的文件大小和保留数量
|
||
export LOG_MAX_SIZE_MB=500
|
||
export LOG_MAX_FILES=30
|
||
|
||
# 指定日志目录
|
||
./new-api --log-dir=/var/log/oneapi
|
||
```
|
||
|
||
### 2. 开发环境配置
|
||
|
||
```bash
|
||
# 使用 DEBUG 级别查看详细信息
|
||
export DEBUG=true
|
||
|
||
# 使用 Text 格式,便于阅读
|
||
export LOG_FORMAT=text
|
||
|
||
# 较小的文件大小和保留数量
|
||
export LOG_MAX_SIZE_MB=50
|
||
export LOG_MAX_FILES=7
|
||
|
||
./new-api --log-dir=./logs
|
||
```
|
||
|
||
### 3. 容器环境配置
|
||
|
||
```bash
|
||
# 只输出到标准输出,由容器运行时管理日志
|
||
./new-api
|
||
|
||
# 或者使用 JSON 格式便于日志收集系统处理
|
||
export LOG_FORMAT=json
|
||
./new-api
|
||
```
|
||
|
||
## 🔍 日志分析
|
||
|
||
### 使用 grep 分析文本日志
|
||
|
||
```bash
|
||
# 查找错误日志
|
||
grep '\[ERROR\]' logs/oneapi.log
|
||
|
||
# 查找特定请求的所有日志
|
||
grep 'abc123' logs/*.log
|
||
|
||
# 查看最近的警告和错误
|
||
tail -f logs/oneapi.log | grep -E '\[(WARN|ERROR)\]'
|
||
|
||
# 查找包含特定关键词的日志
|
||
grep 'database' logs/oneapi.log
|
||
|
||
# 查看今天的所有错误
|
||
grep "\[ERROR\] $(date +%Y/%m/%d)" logs/oneapi.log
|
||
```
|
||
|
||
### 使用 jq 分析 JSON 日志
|
||
|
||
```bash
|
||
# 提取所有错误日志
|
||
cat logs/oneapi.log | jq 'select(.level=="ERROR")'
|
||
|
||
# 统计各级别日志数量
|
||
cat logs/oneapi.log | jq -r '.level' | sort | uniq -c
|
||
|
||
# 查找特定时间范围的日志
|
||
cat logs/oneapi.log | jq 'select(.time >= "2024-01-02 15:00:00" and .time <= "2024-01-02 16:00:00")'
|
||
```
|
||
|
||
## 📊 性能优化
|
||
|
||
1. **异步日志轮转**: 轮转操作在后台 goroutine 中执行,不阻塞主程序
|
||
2. **批量写入检查**: 每 1000 次写入才检查一次轮转条件,减少 I/O 开销
|
||
3. **读写锁**: 使用 `sync.RWMutex` 保护日志器,提高并发性能
|
||
4. **零分配**: `slog` 库在大多数情况下实现零内存分配
|
||
|
||
## 🚨 故障排查
|
||
|
||
### 日志文件未创建
|
||
|
||
- 检查日志目录是否存在且有写入权限
|
||
- 确认启动时指定了 `--log-dir` 参数
|
||
|
||
### 日志文件过多
|
||
|
||
- 调整 `LOG_MAX_FILES` 环境变量
|
||
- 手动清理不需要的旧日志文件
|
||
|
||
### 日志级别不正确
|
||
|
||
- 检查 `LOG_LEVEL` 环境变量是否正确设置
|
||
- 确认 `DEBUG` 环境变量的值(会覆盖 LOG_LEVEL)
|
||
|
||
## 📖 相关文档
|
||
|
||
- [Go slog 官方文档](https://pkg.go.dev/log/slog)
|
||
- [结构化日志最佳实践](https://go.dev/blog/slog)
|
||
|