// 以 Python logging 为例
import os
import logging
LOG_LEVEL_MAP = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR
}
level_str = os.getenv("LOG_LEVEL", "info").lower()
level = LOG_LEVEL_MAP.get(level_str, logging.INFO)
logging.basicConfig(level=level)
**2. 日志格式选择与切换**
原型阶段使用人类可读的文本格式,生产阶段切换为JSON结构化格式。两种格式由一个配置开关控制,不修改代码逻辑。
# 原型阶段格式
# 输出示例:
# 2025-03-21 14:23:45.123 | INFO | agent.brain:42 | LLM response received in 2.3s
# 生产阶段格式(JSON)
# 输出示例:
# {"timestamp":"2025-03-21T14:23:45.123Z","level":"INFO","logger":"agent.brain","line":42,"message":"LLM response received","latency_ms":2300}
**3. 异步处理器与缓冲配置**
生产环境必须将同步写入改为异步日志处理器,降低业务线程阻塞风险。
# Python 示例:使用 QueueHandler + QueueListener
import logging
import logging.handlers
import queue
log_queue = queue.Queue(-1)
queue_handler = logging.handlers.QueueHandler(log_queue)
file_handler = logging.FileHandler("agent.log")
file_handler.setFormatter(json_formatter)
listener = logging.handlers.QueueListener(log_queue, file_handler)
listener.start()
**4. 日志轮转策略部署**
使用基于时间的轮转(每日切分)或基于大小的轮转(每100MB切分),保留最近30个文件后自动删除最旧文件。
## 日志轮转配置示例
生产环境推荐同时配置**基于时间**和**基于大小**的双重轮转策略,以应对突发流量导致的日志暴增。
# Python logging 配置——同时启用时间 + 大小轮转
import logging.handlers
rotating_handler = logging.handlers.TimedRotatingFileHandler(
filename="agent.log",
when="midnight", # 每天午夜轮转
interval=1,
backupCount=30,
encoding="utf-8"
)
# 同时设置单文件大小上限(100MB),防止单文件过大
rotating_handler.maxBytes = 100 * 1024 * 1024
rotating_handler.rolloverAt = 0
# Linux logrotate 配置文件(外部轮转方案)
# 路径:/etc/logrotate.d/agent
/var/log/agent/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
copytruncate
maxsize 100M
postrotate
kill -HUP `cat /var/run/agent.pid`
endscript
}
## 调试方法
在开发环境验证日志配置的正确性,可以使用以下调试步骤:
1. **环境变量覆盖测试**:分别设置 `LOG_LEVEL=debug` 和 `LOG_LEVEL=warning`,确认日志输出量与预期一致。
2. **结构化格式验证**:将日志输出通过管道导入 `jq`(JSON解析工具),检查JSON是否完整合法。
3. **轮转功能验证**:手动触发轮转事件,检查是否生成新文件、旧文件是否被压缩归档。
4. **磁盘空间监控**:使用 `watch -n 5 du -sh /var/log/agent/` 观察日志目录大小,确保轮转策略生效。
# 验证结构化日志格式
python agent.py --log-level warning 2>&1 | head -5 | jq .
# 预期输出类似:
# {
# "timestamp": "2025-03-21T14:30:00.123Z",
# "level": "WARNING",
# "logger": "agent.executor",
# "message": "Retry attempt 2/3 for task-abc123"
# }
## 部署步骤
1. **配置准备**:在部署配置中心(如Consul、Kubernetes ConfigMap)中定义日志级别、格式、输出路径和轮转参数。
2. **目录权限**:确保Agent进程对日志目录有读写权限,避免启动时因权限不足导致日志丢失。
3. **异步处理器预热**:在启动脚本中加载QueueListener,避免启动前几秒的日志被阻塞。
4. **轮转脚本部署**:若使用系统logrotate,需提前放置配置文件并测试 `logrotate -d` 无报错。
5. **监控告警绑定**:将 `WARNING` 和 `ERROR` 级别日志接入告警通道(如Alertmanager),实现异常自动响应。
## 常见错误及优化
| 常见错误 | 原因分析 | 优化方案 |
|---------|----------|----------|
| 生产环境仍输出DEBUG日志 | 环境变量未正确传递,或代码中硬编码了日志级别 | 在启动入口统一读取环境变量,禁止代码内手动设置级别 |
| 日志文件无限增长导致磁盘满 | 未配置轮转策略或backupCount过大 | 严格限制backupCount≤30,同时设置maxBytes≤500MB |
| 结构化日志JSON解析失败 | 字段中包含未转义的特殊字符(如换行符) | 在日志处理器中使用 `json.dumps(ensure_ascii=True)` |
| 异步日志丢失部分记录 | 进程异常退出时队列未排空 | 注册 `atexit` 钩子,确保Listener在进程退出前完成写入 |
🔔 生产部署黄金检验点: 在灰度发布阶段,先验证日志目录大小变化是否符合预期(每日增量≤100MB),再进行全量推送。日志轮转的配置错误是线上故障的常见根源。
💡 调试日志保留技巧: 原型阶段的完整调试日志不必全部丢弃。建议将生产环境的日志级别设为INFO,同时开启一个独立的
debug.log 捕获DEBUG级别日志,但轮转周期缩短为1小时,保留最近24小时用于故障回溯。