mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 05:41:37 +00:00
6.9 KiB
6.9 KiB
日志系统说明
本项目使用 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: 错误信息
⚙️ 配置方式
环境变量配置
# 日志目录(必需,否则只输出到控制台)
--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
命令行参数
# 启动时指定日志目录
./new-api --log-dir=./logs
# 如果不指定日志目录,日志只输出到控制台
./new-api
📝 使用示例
基础使用
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 格式:
{"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 # 更早的日志
└── ... # 最多保留配置数量的历史文件
🔄 日志轮转机制
轮转触发条件
- 文件大小检查: 每写入 1000 条日志后检查一次文件大小
- 启动时日期检查: 程序启动时检查日志文件的修改日期,如果不是今天则轮转
- 自动清理: 轮转时自动删除超过保留数量的旧日志文件
注意: 日志不会在运行时动态检查日期变化。如果需要每天自动轮转日志,建议:
- 使用定时任务(如 cron)每天重启服务
- 或者配置较小的日志文件大小,让它自动按大小轮转
轮转流程
- 检测到需要轮转时,关闭当前日志文件
- 将
oneapi.log重命名为oneapi.YYYY-MM-DD-HHmmss.log - 创建新的
oneapi.log文件 - 异步清理超过数量限制的旧日志文件
- 记录轮转事件到新日志文件
🎯 最佳实践
1. 生产环境配置
# 使用 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. 开发环境配置
# 使用 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. 容器环境配置
# 只输出到标准输出,由容器运行时管理日志
./new-api
# 或者使用 JSON 格式便于日志收集系统处理
export LOG_FORMAT=json
./new-api
🔍 日志分析
使用 grep 分析文本日志
# 查找错误日志
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 日志
# 提取所有错误日志
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")'
📊 性能优化
- 异步日志轮转: 轮转操作在后台 goroutine 中执行,不阻塞主程序
- 批量写入检查: 每 1000 次写入才检查一次轮转条件,减少 I/O 开销
- 读写锁: 使用
sync.RWMutex保护日志器,提高并发性能 - 零分配:
slog库在大多数情况下实现零内存分配
🚨 故障排查
日志文件未创建
- 检查日志目录是否存在且有写入权限
- 确认启动时指定了
--log-dir参数
日志文件过多
- 调整
LOG_MAX_FILES环境变量 - 手动清理不需要的旧日志文件
日志级别不正确
- 检查
LOG_LEVEL环境变量是否正确设置 - 确认
DEBUG环境变量的值(会覆盖 LOG_LEVEL)