Skip to content

5.2 日志系统

引言

小白理解 - 什么是日志?

日志 = 程序运行时写的"日记"

类比:飞机的黑匣子

  • 飞机正常飞行时:记录高度、速度、方向...
  • 飞机出事后:查看黑匣子,分析原因

为什么需要日志?

场景没有日志有日志
程序崩溃"反正坏了,不知道为啥""看日志,原来是 API 超时"
用户投诉"我也不知道他做了什么""看日志,他输入了非法字符"
性能问题"感觉慢,不知道哪里慢""看日志,数据库查询用了 10 秒"

print 不行吗?

  • print 只能输出到屏幕,程序关了就没了
  • logging 可以保存到文件、分级别、带时间戳

logging 基础

小白理解 - 日志级别是什么?

日志有"紧急程度",从低到高:

级别用途类比
DEBUG详细调试信息便签纸
INFO常规运行信息日记本
WARNING警告(还没出错但要注意)黄色信号灯
ERROR出错了红色警报
CRITICAL严重错误(系统要挂了)紧急求救信号

设置 level=INFO 的意思:只记录 INFO 及以上级别的日志

  • DEBUG 不记录(太琐碎)
  • INFO、WARNING、ERROR、CRITICAL 都记录
python
import logging

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

logger = logging.getLogger(__name__)

# 不同级别的日志
logger.debug("调试信息")      # 不会显示(级别太低)
logger.info("常规信息")       # ✅ 显示
logger.warning("警告信息")    # ✅ 显示
logger.error("错误信息")      # ✅ 显示
logger.critical("严重错误")   # ✅ 显示

代码解读

代码含义
logging.basicConfig(...)配置日志系统
level=logging.INFO只记录 INFO 及以上级别
format='...'日志输出格式
%(asctime)s时间
%(name)s日志器名称
%(levelname)s级别(INFO/ERROR...)
%(message)s日志内容

输出示例

2024-01-15 10:30:00,123 - __main__ - INFO - 常规信息
2024-01-15 10:30:00,124 - __main__ - WARNING - 警告信息

Agent 日志系统

小白理解 - 为什么要自定义日志类?

基础的 logging 只能输出到一个地方

实际需求

  • 详细日志 → 保存到文件(方便查问题)
  • 重要日志 → 显示在屏幕(实时看)

解决:创建自定义日志类,同时输出到多个地方

小白理解 - Handler(处理器)是什么?

Handler = 日志输出到哪里

Handler输出位置
FileHandler文件
StreamHandler屏幕/控制台
RotatingFileHandler自动分割的文件

一个 logger 可以有多个 Handler,日志同时输出到多个地方

python
import logging
from pathlib import Path

class AgentLogger:
    """Agent 日志管理器"""

    def __init__(self, name: str, log_file: str = "agent.log"):
        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.DEBUG)

        # 文件处理器(所有日志都写入文件)
        fh = logging.FileHandler(log_file, encoding="utf-8")
        fh.setLevel(logging.DEBUG)

        # 控制台处理器(只显示 INFO 及以上)
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)

        # 格式化
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)

        self.logger.addHandler(fh)
        self.logger.addHandler(ch)

    def log_api_call(self, endpoint: str, status: str):
        """记录 API 调用"""
        self.logger.info(f"API 调用: {endpoint} - 状态: {status}")

    def log_error(self, error: Exception):
        """记录错误"""
        self.logger.error(f"错误: {error}", exc_info=True)

# 使用
logger = AgentLogger("ResearchBot")
logger.log_api_call("/chat", "success")

代码结构图解

AgentLogger

 └── logger(日志器)

      ├── FileHandler(文件处理器)
      │    └── 所有日志 → agent.log 文件

      └── StreamHandler(控制台处理器)
           └── INFO 及以上 → 屏幕显示

效果

  • DEBUG 日志:只写入文件
  • INFO/WARNING/ERROR:既写入文件,又显示在屏幕

实战:给 Agent 添加日志

python
class Agent:
    def __init__(self, name: str):
        self.name = name
        self.logger = AgentLogger(name)

    def chat(self, user_input: str) -> str:
        self.logger.logger.info(f"用户输入: {user_input}")

        try:
            # 处理逻辑
            response = f"收到: {user_input}"
            self.logger.logger.info(f"响应: {response}")
            return response

        except Exception as e:
            self.logger.log_error(e)
            return "抱歉,出错了"

# 使用
agent = Agent("ChatBot")
agent.chat("你好")

本节小结

概念一句话解释记忆口诀
loggingPython 内置日志模块logging = 日记本
日志级别DEBUG < INFO < WARNING < ERROR < CRITICAL越严重越高
Handler日志输出到哪里Handler = 输出口
Formatter日志格式格式化 = 排版

何时用什么级别?

级别用途
DEBUG开发调试时的详细信息
INFO正常运行的记录(API 调用、用户操作)
WARNING不影响运行但需要注意(配额快用完)
ERROR出错了但程序还能继续
CRITICAL严重错误,程序可能要挂

下一节:5.3 调试技巧

基于 MIT 许可证发布。内容版权归作者所有。