J'Blog

第 14 课 · 日常

语义检索

基于 Chroma 向量库,与 Workspace 知识库分离。用自然语言描述你想查的内容。 非管理员每人每天可检索 5 次(消耗站点 AI 配额)。

日志记录系统

原文:logging 日志

一句话

为Python应用提供灵活的事件日志记录系统,支持多级别、多目标和格式化输出。

什么时候翻这页

  1. 需要为Agent或工具调用添加详细的调试和监控日志
  2. 需要结构化输出日志内容,便于后续分析和监控
  3. 在多线程环境中记录异步操作时需要确保线程安全
  4. 需要过滤和分类不同重要性的日志信息

核心概念

  1. Logger(记录器):日志系统的入口点,应用程序代码直接使用它来记录日志消息
  2. Handler(处理器):将日志记录发送到适当的目标(如文件、控制台、网络等)
  3. Formatter(格式器):指定日志记录的最终输出格式
  4. Filter(过滤器):提供更细粒度的控制,决定哪些日志记录应该被输出
  5. LogRecord(日志记录):包含被记录事件的所有信息的对象
  6. 日志级别:表示日志消息的严重程度,包括DEBUG、INFO、WARNING、ERROR、CRITICAL

怎么做

  1. 基本日志记录:
import logging

# 获取记录器
logger = logging.getLogger(__name__)

# 记录不同级别的消息
logger.debug("调试信息")
logger.info("一般信息")
logger.warning("警告信息")
logger.error("错误信息")
logger.critical("严重错误")
  1. 配置日志系统:
# 基本配置
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)
  1. 使用上下文信息:
# 使用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("处理请求")
  1. 结构化日志输出:
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 开发的联系

  1. 工具调用监控:使用日志记录Agent调用工具的过程和结果,便于调试和审计
  2. 决策过程追踪:记录Agent的决策逻辑和推理过程,提高透明度和可解释性
  3. 异步操作日志:在处理异步工具调用时,使用线程安全的日志记录确保操作顺序正确
  4. 结构化输出:通过自定义格式器生成结构化日志,便于后续分析和监控Agent行为

初学者易错点

  1. 忘记配置日志级别:如果不设置日志级别,可能看不到重要的调试信息
  2. 直接实例化Logger:应该使用getLogger()方法获取记录器实例,而不是直接实例化
  3. 忽略日志传播:子记录器的消息默认会传播到父记录器,可能导致重复日志
  4. 在处理器中调用日志API:可能导致死锁,因为处理器和日志API都可能使用锁
  5. 不处理异常:日志系统本身可能抛出异常,需要确保不会影响主程序流程

相关词条

  • library-logging-config 日志配置高级技巧
  • library-logging-handlers 日志处理器详解
  • library-logging-formatters 日志格式化器定制
  • library-threading 多线程编程基础
  • library-json JSON数据处理
  • library-asyncio 异步编程基础

官方原文:https://docs.python.org/zh-cn/3/library/logging.html