日志记录系统
原文:logging 日志
一句话
为Python应用提供灵活的事件日志记录系统,支持多级别、多目标和格式化输出。
什么时候翻这页
- 需要为Agent或工具调用添加详细的调试和监控日志
- 需要结构化输出日志内容,便于后续分析和监控
- 在多线程环境中记录异步操作时需要确保线程安全
- 需要过滤和分类不同重要性的日志信息
核心概念
- Logger(记录器):日志系统的入口点,应用程序代码直接使用它来记录日志消息
- Handler(处理器):将日志记录发送到适当的目标(如文件、控制台、网络等)
- Formatter(格式器):指定日志记录的最终输出格式
- Filter(过滤器):提供更细粒度的控制,决定哪些日志记录应该被输出
- LogRecord(日志记录):包含被记录事件的所有信息的对象
- 日志级别:表示日志消息的严重程度,包括DEBUG、INFO、WARNING、ERROR、CRITICAL
怎么做
- 基本日志记录:
import logging
# 获取记录器
logger = logging.getLogger(__name__)
# 记录不同级别的消息
logger.debug("调试信息")
logger.info("一般信息")
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误")
- 配置日志系统:
# 基本配置
logging.basicConfig(
filename='app.log',
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# 或者使用更灵活的配置方式
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# 创建处理器
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
# 创建格式器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# 添加处理器到记录器
logger.addHandler(handler)
- 使用上下文信息:
# 使用extra参数添加上下文信息
logger.info("处理请求", extra={
'request_id': '12345',
'user_id': 'user1'
})
# 使用LoggerAdapter添加上下文
class ContextAdapter(logging.LoggerAdapter):
def __init__(self, logger, extra):
super().__init__(logger, extra)
def process(self, msg, kwargs):
kwargs['extra'] = self.extra
return msg, kwargs
context_logger = ContextAdapter(logger, {'request_id': '12345'})
context_logger.info("处理请求")
- 结构化日志输出:
import json
class JsonFormatter(logging.Formatter):
def format(self, record):
log_data = {
'timestamp': self.formatTime(record),
'level': record.levelname,
'message': record.getMessage(),
'module': record.module,
'function': record.funcName,
'line': record.lineno
}
if hasattr(record, 'extra_data'):
log_data.update(record.extra_data)
return json.dumps(log_data)
handler = logging.StreamHandler()
handler.setFormatter(JsonFormatter())
logger.addHandler(handler)
# 记录带有额外数据的日志
logger.info("处理完成", extra={'extra_data': {'request_id': '12345'}})
命令 / API 速查
| 函数/方法 | 描述 |
|---|---|
logging.getLogger(name) | 获取指定名称的记录器 |
logger.debug(msg, *args, **kwargs) | 记录DEBUG级别的消息 |
logger.info(msg, *args, **kwargs) | 记录INFO级别的消息 |
logger.warning(msg, *args, **kwargs) | 记录WARNING级别的消息 |
logger.error(msg, *args, **kwargs) | 记录ERROR级别的消息 |
logger.critical(msg, *args, **kwargs) | 记录CRITICAL级别的消息 |
logger.exception(msg, *args, **kwargs) | 记录包含异常信息的ERROR级别消息 |
logging.basicConfig(**kwargs) | 配置根记录器的基本设置 |
logger.setLevel(level) | 设置记录器的日志级别 |
logger.addHandler(handler) | 添加处理器到记录器 |
logger.removeHandler(handler) | 从记录器移除处理器 |
handler.setFormatter(formatter) | 设置处理器的格式器 |
logging.disable(level) | 禁用指定级别及以下的日志 |
与 Agent 开发的联系
- 工具调用监控:使用日志记录Agent调用工具的过程和结果,便于调试和审计
- 决策过程追踪:记录Agent的决策逻辑和推理过程,提高透明度和可解释性
- 异步操作日志:在处理异步工具调用时,使用线程安全的日志记录确保操作顺序正确
- 结构化输出:通过自定义格式器生成结构化日志,便于后续分析和监控Agent行为
初学者易错点
- 忘记配置日志级别:如果不设置日志级别,可能看不到重要的调试信息
- 直接实例化Logger:应该使用
getLogger()方法获取记录器实例,而不是直接实例化 - 忽略日志传播:子记录器的消息默认会传播到父记录器,可能导致重复日志
- 在处理器中调用日志API:可能导致死锁,因为处理器和日志API都可能使用锁
- 不处理异常:日志系统本身可能抛出异常,需要确保不会影响主程序流程
相关词条
library-logging-config日志配置高级技巧library-logging-handlers日志处理器详解library-logging-formatters日志格式化器定制library-threading多线程编程基础library-jsonJSON数据处理library-asyncio异步编程基础