【Agent从入门到实践】44 监控与日志:添加监控指标、日志记录,方便问题排查

文章目录

目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步。想要系统学习AI知识的朋友可以看看我的教程http://blog.csdn.net/jiangjunshow,教程通俗易懂,风趣幽默,从深度学习基础原理到各领域实战应用都有讲解。

本文章限时免费,整个专栏写完后将转为收费专栏,请勿转载

各位小伙伴,咱们的多Agent框架现在能打包、能部署、能对外提供API服务了,但如果现在服务出问题了,比如:API接口响应突然变慢、Agent执行任务报错、容器CPU占用飙到100%,你能快速找到原因吗?

如果没加日志和监控,大概率只能对着终端翻零散的输出,或者凭经验瞎猜,排查问题耗时又费力,这在生产环境绝对是大忌!而完善的日志+监控,就是服务的"眼睛和耳朵":

  • 日志:把服务运行的每一步(请求接收、Agent执行、参数传递、错误信息)都按规范记录下来,出问题了顺着日志一查就知道根因;
  • 监控:实时采集服务的核心指标(QPS、响应时间、错误率、CPU/内存占用、Agent执行次数),指标异常时能第一时间发现,还能通过可视化面板直观看到服务状态。

这篇咱们就给多Agent框架+API服务做生产级可观测性改造 ,分两大块实战:一是搭建分级日志系统 ,实现日志分级、链路追踪、文件持久化;二是添加监控指标埋点,实现核心指标采集、对接Prometheus。所有代码都无缝衔接之前的API封装和Docker部署,还会教你如何快速对接Grafana做可视化监控,最后给出日志排查和监控告警的实战技巧,让你的Agent服务真正做到"问题可查、状态可监控"~


一、实战前置:准备工作(2分钟搞定)

本次实战不用新增太多依赖,只需要安装一个监控指标采集的库,同时保持框架目录结构不变,新增utils/目录存放日志和监控的工具类,准备工作就两步:

1. 完善requirements.txt,新增监控依赖

在原有依赖基础上,新增prometheus-client(Prometheus官方Python客户端,用于指标埋点和采集),这是2025年Python服务对接Prometheus的标配,轻量无侵入:

txt 复制代码
# requirements.txt 新增监控依赖
python>=3.8,<3.12
# 原有依赖省略...
fastapi==0.112.0
uvicorn==0.30.6
pyjwt==2.8.0
# 新增监控指标采集依赖
prometheus-client==0.20.0
# 可选:日志轮转,避免单个日志文件过大
logging-handlers-rotating-file==0.1.0

2. 确认框架目录结构

新增utils/目录,用于存放日志工具类log_utils.py和监控工具类metrics_utils.py,目录结构如下(和之前完全兼容):

复制代码
multi-agent-framework/  # 框架根目录
├── api/                 # API封装目录
│   └── api_server.py    # API核心代码
├── agents/              # Agent目录
├── framework/           # 框架核心目录
├── tools/               # 工具目录
├── utils/               # 新增:工具类目录
│   ├── log_utils.py     # 新增:日志工具类(分级、链路追踪)
│   └── metrics_utils.py # 新增:监控工具类(指标埋点、采集)
├── .env                 # 环境变量
├── requirements.txt     # 依赖清单
├── Dockerfile           # Docker打包配置
└── .dockerignore        # 忽略文件

二、核心实战1:搭建生产级日志系统(问题排查的核心)

日志是排查问题的根本,生产级的日志系统绝对不能是简单的print(),必须满足分级记录、链路追踪、文件持久化、日志轮转 四个核心要求,咱们用Python内置的logging模块做封装,实现一个通用的日志工具类,整个框架+API服务统一使用,保证日志格式一致、可追溯。

1. 编写日志工具类(utils/log_utils.py)

这是日志系统的核心,实现日志分级(DEBUG/INFO/WARNING/ERROR/CRITICAL)、请求ID链路追踪、日志文件轮转、格式标准化,代码可直接复制,每一行都有注释:

python 复制代码
# utils/log_utils.py 生产级日志工具类
import logging
import os
import uuid
from logging.handlers import RotatingFileHandler
from datetime import datetime
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()
# 日志配置(从环境变量读取,方便Docker部署动态修改)
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()  # 日志级别:DEBUG/INFO/WARNING/ERROR/CRITICAL
LOG_DIR = os.getenv("LOG_DIR", "logs")  # 日志存储目录
LOG_MAX_BYTES = int(os.getenv("LOG_MAX_BYTES", 1024 * 1024 * 50))  # 单个日志文件最大50M
LOG_BACKUP_COUNT = int(os.getenv("LOG_BACKUP_COUNT", 10))  # 日志文件最多保留10个
LOG_FORMAT = (
    "%(asctime)s - %(name)s - %(levelname)s - %(request_id)s - %(message)s"
)  # 标准化日志格式,包含请求ID

# 创建日志目录
os.makedirs(LOG_DIR, exist_ok=True)

def get_logger(name: str, request_id: str = None) -> logging.Logger:
    """
    获取日志实例
    :param name: 日志名称(模块/类名,方便定位)
    :param request_id: 请求ID(链路追踪,所有日志关联同一个请求ID)
    :return: 配置好的logger
    """
    # 初始化logger
    logger = logging.getLogger(name)
    logger.setLevel(LOG_LEVEL)
    # 避免重复添加处理器
    if logger.handlers:
        return logger
    
    # 定义日志格式器:添加请求ID,无请求ID则生成默认值
    class RequestIDFilter(logging.Filter):
        def __init__(self, req_id):
            self.req_id = req_id or f"default-{uuid.uuid4().hex[:8]}"
        
        def filter(self, record):
            record.request_id = self.req_id
            return True
    
    # 格式器
    formatter = logging.Formatter(LOG_FORMAT, datefmt="%Y-%m-%d %H:%M:%S")
    # 请求ID过滤器
    req_filter = RequestIDFilter(request_id)

    # 1. 控制台处理器:输出到终端,方便开发调试
    console_handler = logging.StreamHandler()
    console_handler.setLevel(LOG_LEVEL)
    console_handler.setFormatter(formatter)
    console_handler.addFilter(req_filter)

    # 2. 文件处理器:日志持久化,支持轮转(避免文件过大)
    log_file = os.path.join(LOG_DIR, f"agent_{datetime.now().strftime('%Y%m%d')}.log")
    file_handler = RotatingFileHandler(
        filename=log_file,
        maxBytes=LOG_MAX_BYTES,
        backupCount=LOG_BACKUP_COUNT,
        encoding="utf-8"
    )
    file_handler.setLevel(LOG_LEVEL)
    file_handler.setFormatter(formatter)
    file_handler.addFilter(req_filter)

    # 添加处理器
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)
    # 禁用向上传播,避免重复打印
    logger.propagate = False

    return logger

# 测试代码(开发时用,生产环境注释)
if __name__ == "__main__":
    logger = get_logger("test", request_id="test123456")
    logger.debug("这是DEBUG日志:详细调试信息")
    logger.info("这是INFO日志:正常运行信息")
    logger.warning("这是WARNING日志:潜在风险提示")
    logger.error("这是ERROR日志:程序执行错误")
    logger.critical("这是CRITICAL日志:严重错误,服务可能中断")

2. 核心日志功能解析

这个日志工具类是生产级标准,比直接用logging强太多,核心亮点:

  • 日志分级:按DEBUG/INFO/WARNING/ERROR/CRITICAL分级,生产环境可设为INFO,只记录关键信息,避免日志冗余;开发环境设为DEBUG,查看详细调试信息。
  • 链路追踪 :所有日志都包含request_id,一个请求的所有操作(接收请求→Agent执行→返回结果)都用同一个request_id,出问题时按request_id搜日志,直接定位整个请求链路。
  • 日志轮转:单个日志文件最大50M,最多保留10个,避免日志文件无限增大占满磁盘。
  • 格式标准化:所有日志统一格式「时间-日志名-级别-request_id-内容」,方便后续日志分析工具(如ELK)解析。
  • 全局通用:整个框架所有模块都可以调用这个工具类,保证日志格式一致。

3. 框架全量接入日志系统(替换所有print/原生logging)

接下来把日志工具类接入到API服务、Agent框架核心、各个Agent 中,实现全链路日志记录,核心原则:关键操作记INFO,参数/调试记DEBUG,异常记ERROR,严重错误记CRITICAL

(1)API服务接入日志(api/api_server.py)

替换原有原生logging,使用新的日志工具类,保证每个请求的日志都关联同一个request_id:

python 复制代码
# api/api_server.py 改造日志部分
import uuid
# 替换原有logging导入,导入新的日志工具类
from utils.log_utils import get_logger
# 注释原有logging配置代码...

# 初始化FastAPI应用
app = FastAPI(
    title="多Agent框架API服务",
    description="2025优化版多Agent框架标准化API,带日志和监控",
    version="1.0.0"
)

# 全局初始化Agent框架(不变)
MASTER_AGENT = MasterAgent()
SLAVE_AGENTS = [SearchSlaveAgent(), CodeSlaveAgent(), WriteSlaveAgent()]
AGENT_FRAMEWORK = MultiAgentFramework(
    collab_mode="parallel",
    agents={"master": MASTER_AGENT, "slaves": SLAVE_AGENTS}
)

# 新增:每次请求生成唯一request_id,并存入请求状态
@app.middleware("http")
async def add_request_id(request: Request, call_next):
    # 生成唯一request_id(UUID8位,简洁且唯一)
    request_id = uuid.uuid4().hex[:8]
    # 将request_id存入请求状态
    request.state.request_id = request_id
    # 执行后续请求
    response = await call_next(request)
    # 响应头添加request_id,方便调用方追溯
    response.headers["X-Request-ID"] = request_id
    return response

# 改造健康检查接口
@app.get("/health", summary="服务健康检查")
async def health_check(request: Request):
    # 获取当前请求的request_id
    request_id = request.state.request_id
    # 获取日志实例,关联request_id
    logger = get_logger("api.health", request_id)
    try:
        logger.info("健康检查请求接收,开始检查服务状态")
        if AGENT_FRAMEWORK:
            logger.info("服务健康检查通过,框架初始化正常")
            return BaseResponse(
                code=200,
                msg="多Agent框架API服务运行正常",
                data={"service_status": "running"},
                request_id=request_id,
                timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            )
        else:
            logger.critical("服务健康检查失败,Agent框架初始化失败")
            raise Exception("Agent框架初始化失败")
    except Exception as e:
        logger.error(f"服务健康检查失败,错误原因:{str(e)}", exc_info=True)
        return BaseResponse(
            code=500,
            msg=f"健康检查失败:{str(e)}",
            data=None,
            request_id=request_id,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )

# 改造Agent执行接口(核心)
@app.post("/api/v1/agent/run", summary="Agent单任务执行")
async def run_agent(request: Request, task: AgentTaskRequest, user_info: dict = Depends(verify_access_token)):
    request_id = request.state.request_id
    logger = get_logger("api.run_agent", request_id)
    try:
        # 记录请求信息(关键参数记INFO,详细参数记DEBUG)
        logger.info(f"Agent任务请求接收,用户ID:{user_info['user_id']},协作模式:{task.collab_mode}")
        logger.debug(f"Agent任务详细参数:user_task={task.user_task[:100]}...")
        # 校验协作模式
        valid_modes = ["parallel", "master_slave", "division", "competition"]
        if task.collab_mode not in valid_modes:
            logger.warning(f"非法协作模式请求,请求模式:{task.collab_mode},合法模式:{valid_modes}")
            raise HTTPException(status_code=400, detail=f"非法协作模式,可选:{valid_modes}")
        # 执行Agent任务
        logger.info("开始执行Agent任务,框架协作模式已切换")
        frame = MultiAgentFramework(collab_mode=task.collab_mode, agents={"master": MASTER_AGENT, "slaves": SLAVE_AGENTS})
        task_result = frame.run(task.user_task)
        # 记录执行成功
        logger.info("Agent任务执行完成,开始返回结果")
        logger.debug(f"Agent任务执行结果:{task_result[:100]}...")
        return BaseResponse(
            code=200,
            msg="Agent任务执行成功",
            data={"collab_mode": task.collab_mode, "task_result": task_result},
            request_id=request_id,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )
    except HTTPException as e:
        logger.warning(f"Agent任务执行失败,参数错误:{e.detail}")
        return BaseResponse(
            code=400,
            msg=f"参数错误:{e.detail}",
            data=None,
            request_id=request_id,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )
    except Exception as e:
        logger.error(f"Agent任务执行失败,服务器内部错误:{str(e)}", exc_info=True)
        return BaseResponse(
            code=500,
            msg=f"服务器内部错误:{str(e)[:100]}",
            data=None,
            request_id=request_id,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )
(2)Agent框架核心接入日志(framework/core.py)

在框架核心执行逻辑中添加日志,记录Agent的创建、任务分发、执行结果,方便定位框架内部问题:

python 复制代码
# framework/core.py 接入日志工具类
from utils.log_utils import get_logger

class MultiAgentFramework:
    def __init__(self, collab_mode: str, agents: dict):
        # 初始化日志(框架核心模块,无request_id时用默认值)
        self.logger = get_logger("framework.core")
        self.collab_mode = collab_mode
        self.master_agent = agents.get("master")
        self.slave_agents = agents.get("slaves", [])
        self.logger.info(f"MultiAgent框架初始化完成,协作模式:{collab_mode},从Agent数量:{len(self.slave_agents)}")
        self.logger.debug(f"框架初始化详细信息:master_agent={self.master_agent.__class__.__name__},slave_agents={[a.__class__.__name__ for a in self.slave_agents]}")

    def run(self, user_task: str):
        self.logger.info(f"框架开始执行用户任务,任务描述:{user_task[:50]}...")
        try:
            # 根据协作模式执行任务(原有逻辑不变)
            if self.collab_mode == "parallel":
                self.logger.info("采用并行协作模式,开始分发任务到所有从Agent")
                result = self._run_parallel(user_task)
            elif self.collab_mode == "master_slave":
                self.logger.info("采用主从协作模式,主Agent开始分发任务")
                result = self._run_master_slave(user_task)
            else:
                self.logger.warning(f"未识别的协作模式:{self.collab_mode},使用默认并行模式")
                result = self._run_parallel(user_task)
            self.logger.info("用户任务执行完成,框架返回执行结果")
            return result
        except Exception as e:
            self.logger.error(f"框架执行用户任务失败,错误原因:{str(e)}", exc_info=True)
            raise e

    # 改造并行执行方法
    def _run_parallel(self, user_task: str):
        self.logger.debug("开始并行执行任务,创建异步执行池")
        # 原有异步执行逻辑...
        self.logger.debug("并行任务执行完成,合并所有从Agent结果")
        return merged_result
(3)各个Agent接入日志(agents/master_agent.py/agents/slave_agents.py)

在主Agent和从Agent中添加日志,记录任务接收、工具调用、结果返回,定位单个Agent的问题:

python 复制代码
# agents/master_agent.py 接入日志
from utils.log_utils import get_logger

class MasterAgent:
    def __init__(self):
        self.logger = get_logger("agent.master")
        self.logger.info("主Agent初始化完成,开始加载任务分发策略")

    def dispatch_task(self, user_task: str, slave_agents: list):
        self.logger.info(f"主Agent接收分发任务,用户任务:{user_task[:50]}...")
        self.logger.debug(f"从Agent列表:{[a.__class__.__name__ for a in slave_agents]}")
        # 原有任务分发逻辑...
        self.logger.info("主Agent任务分发完成,返回各从Agent执行任务")
        return task_list

# agents/slave_agents.py 接入日志
from utils.log_utils import get_logger

class SearchSlaveAgent:
    def __init__(self):
        self.logger = get_logger("agent.slave.search")
        self.logger.info("检索从Agent初始化完成,加载向量检索工具")

    def run(self, task: str):
        self.logger.info(f"检索从Agent接收执行任务,任务:{task[:50]}...")
        try:
            # 原有检索逻辑...
            self.logger.info("检索从Agent任务执行完成,返回检索结果")
            self.logger.debug(f"检索结果:{result[:100]}...")
            return result
        except Exception as e:
            self.logger.error(f"检索从Agent执行失败,错误原因:{str(e)}", exc_info=True)
            raise e

# 其他从Agent(CodeSlaveAgent/WriteSlaveAgent)按同样方式接入...

4. 配置环境变量(.env),新增日志配置

.env文件中新增日志相关配置,方便在Docker中动态修改,不用改代码:

env 复制代码
# .env 日志配置
LOG_LEVEL=INFO
LOG_DIR=logs
LOG_MAX_BYTES=52428800  # 50M
LOG_BACKUP_COUNT=10
# 原有配置...
OPENAI_API_KEY=sk-xxx
API_HOST=0.0.0.0
API_PORT=8000

三、核心实战2:添加监控指标埋点(实时掌握服务状态)

光有日志还不够,日志是"出问题后查原因",而监控是"出问题前发现异常",生产级服务必须有核心指标的实时监控。咱们用prometheus-client给API服务和Agent框架添加核心指标埋点 ,采集的指标包含API服务指标Agent框架指标两大类,同时在FastAPI中添加Prometheus指标采集接口,让Prometheus能自动拉取指标。

1. 编写监控工具类(utils/metrics_utils.py)

封装监控指标的创建和更新方法,实现指标统一管理,支持的指标类型包含:计数器(Counter)、仪表盘(Gauge)、直方图(Histogram),这是Prometheus最常用的三种指标类型,代码可直接复制:

python 复制代码
# utils/metrics_utils.py 生产级监控工具类
from prometheus_client import Counter, Gauge, Histogram, generate_latest, CONTENT_TYPE_LATEST
from prometheus_client.core import REGISTRY
from fastapi import Response

# ===================== 指标定义(统一管理,避免重复创建) =====================
# 【API服务核心指标】
# API请求总数(Counter:只增不减,记录累计次数)
API_REQUEST_TOTAL = Counter(
    "agent_api_request_total",
    "Total number of API requests",
    ["endpoint", "method", "status_code"]  # 标签:接口、请求方法、状态码
)
# API请求响应时间(Histogram:统计分布,如P50/P95/P99)
API_REQUEST_DURATION = Histogram(
    "agent_api_request_duration_seconds",
    "API request duration in seconds",
    ["endpoint", "method"]
)
# 服务当前活跃请求数(Gauge:可增可减,记录当前值)
API_ACTIVE_REQUESTS = Gauge(
    "agent_api_active_requests",
    "Number of active API requests",
    ["endpoint"]
)

# 【Agent框架核心指标】
# Agent任务执行总数(Counter)
AGENT_TASK_TOTAL = Counter(
    "agent_task_total",
    "Total number of Agent tasks executed",
    ["collab_mode", "status"]  # 标签:协作模式、执行状态(成功/失败)
)
# Agent任务执行时间(Histogram)
AGENT_TASK_DURATION = Histogram(
    "agent_task_duration_seconds",
    "Agent task execution duration in seconds",
    ["collab_mode"]
)
# 从Agent数量(Gauge)
AGENT_SLAVE_COUNT = Gauge(
    "agent_slave_count",
    "Number of slave Agents"
)
# 框架资源占用:CPU使用率(Gauge)、内存使用率(Gauge)
AGENT_CPU_USAGE = Gauge(
    "agent_cpu_usage_percent",
    "Agent framework CPU usage percent"
)
AGENT_MEM_USAGE = Gauge(
    "agent_mem_usage_percent",
    "Agent framework memory usage percent"
)

# ===================== 指标操作工具方法 =====================
def record_api_request(endpoint: str, method: str, status_code: int, duration: float):
    """
    记录API请求指标
    :param endpoint: 接口地址
    :param method: 请求方法(GET/POST)
    :param status_code: 响应状态码
    :param duration: 响应时间(秒)
    """
    API_REQUEST_TOTAL.labels(endpoint=endpoint, method=method, status_code=status_code).inc()
    API_REQUEST_DURATION.labels(endpoint=endpoint, method=method).observe(duration)

def record_agent_task(collab_mode: str, status: str, duration: float):
    """
    记录Agent任务执行指标
    :param collab_mode: 协作模式
    :param status: 执行状态(success/failed)
    :param duration: 执行时间(秒)
    """
    AGENT_TASK_TOTAL.labels(collab_mode=collab_mode, status=status).inc()
    AGENT_TASK_DURATION.labels(collab_mode=collab_mode).observe(duration)

def set_agent_resource_metrics(cpu: float, mem: float):
    """
    设置Agent框架资源占用指标
    :param cpu: CPU使用率(0-100)
    :param mem: 内存使用率(0-100)
    """
    AGENT_CPU_USAGE.set(cpu)
    AGENT_MEM_USAGE.set(mem)

# ===================== FastAPI指标采集接口 =====================
async def metrics():
    """
    Prometheus指标采集接口,默认地址:/metrics
    Prometheus会定时调用此接口拉取指标
    """
    return Response(
        content=generate_latest(REGISTRY),
        media_type=CONTENT_TYPE_LATEST
    )

# 初始化从Agent数量指标
def init_agent_metrics(slave_count: int):
    """初始化Agent框架指标"""
    AGENT_SLAVE_COUNT.set(slave_count)
    AGENT_CPU_USAGE.set(0.0)
    AGENT_MEM_USAGE.set(0.0)

2. 核心监控指标解析

采集的指标分为API服务指标Agent框架指标,覆盖服务运行的核心维度,Prometheus拉取后可做可视化和告警,关键指标说明:

指标类型 指标名称 指标含义 作用
计数器 agent_api_request_total API请求累计数 统计各接口QPS、错误率
直方图 agent_api_request_duration API请求响应时间 分析接口响应速度,看P95/P99
仪表盘 agent_api_active_requests 活跃请求数 监控服务并发量
计数器 agent_task_total Agent任务执行累计数 统计各模式任务执行次数/成功率
直方图 agent_task_duration Agent任务执行时间 分析Agent执行效率
仪表盘 agent_cpu/mem_usage 框架CPU/内存使用率 监控服务资源占用

3. 框架全量接入监控指标(API+Agent)

将监控指标埋点接入到API服务和Agent框架中,实现请求/任务指标自动记录资源指标定时采集,核心是在关键节点(请求开始/结束、任务开始/结束)调用监控工具类的方法更新指标。

(1)API服务接入监控指标(api/api_server.py)

添加请求耗时统计、活跃请求数统计,在请求开始和结束时更新指标,同时添加资源指标定时采集:

python 复制代码
# api/api_server.py 接入监控指标
import time
import psutil
from fastapi import BackgroundTasks
# 导入监控工具类
from utils.metrics_utils import (
    record_api_request, API_ACTIVE_REQUESTS,
    init_agent_metrics, set_agent_resource_metrics,
    metrics as prom_metrics
)

# 全局初始化Agent指标(从Agent数量)
init_agent_metrics(len(SLAVE_AGENTS))
# 注册Prometheus指标采集接口
app.add_api_route("/metrics", prom_metrics, methods=["GET"], summary="Prometheus指标采集接口")

# 新增:定时采集Agent框架资源指标(后台任务,每5秒执行一次)
def collect_resource_metrics():
    """采集CPU和内存使用率,后台定时执行"""
    # 获取当前进程的资源占用
    process = psutil.Process()
    cpu_usage = process.cpu_percent(interval=1)
    mem_usage = process.memory_percent()
    # 设置资源指标
    set_agent_resource_metrics(cpu_usage, mem_usage)

# 改造请求中间件,添加请求耗时和活跃请求数统计
@app.middleware("http")
async def add_request_id_and_metrics(request: Request, call_next):
    request_id = uuid.uuid4().hex[:8]
    request.state.request_id = request_id
    # 监控:记录请求开始时间,增加活跃请求数
    start_time = time.time()
    endpoint = request.url.path
    method = request.method
    API_ACTIVE_REQUESTS.labels(endpoint=endpoint).inc()
    # 执行请求
    response = await call_next(request)
    # 监控:减少活跃请求数,计算请求耗时,记录API指标
    API_ACTIVE_REQUESTS.labels(endpoint=endpoint).dec()
    duration = time.time() - start_time
    status_code = response.status_code
    record_api_request(endpoint, method, status_code, duration)
    # 添加response header
    response.headers["X-Request-ID"] = request_id
    response.headers["X-Request-Duration"] = f"{duration:.3f}s"
    return response

# 改造Agent执行接口,添加Agent任务指标记录
@app.post("/api/v1/agent/run", summary="Agent单任务执行")
async def run_agent(request: Request, task: AgentTaskRequest, user_info: dict = Depends(verify_access_token), background_tasks: BackgroundTasks = BackgroundTasks()):
    # 添加上台任务,定时采集资源指标
    background_tasks.add_task(collect_resource_metrics)
    request_id = request.state.request_id
    logger = get_logger("api.run_agent", request_id)
    try:
        logger.info(f"Agent任务请求接收,用户ID:{user_info['user_id']},协作模式:{task.collab_mode}")
        # 记录Agent任务开始时间
        task_start = time.time()
        # 原有逻辑:校验模式、执行任务
        valid_modes = ["parallel", "master_slave", "division", "competition"]
        if task.collab_mode not in valid_modes:
            logger.warning(f"非法协作模式请求:{task.collab_mode}")
            raise HTTPException(status_code=400, detail=f"非法协作模式,可选:{valid_modes}")
        frame = MultiAgentFramework(collab_mode=task.collab_mode, agents={"master": MASTER_AGENT, "slaves": SLAVE_AGENTS})
        task_result = frame.run(task.user_task)
        # 记录Agent任务执行成功指标
        task_duration = time.time() - task_start
        record_agent_task(collab_mode=task.collab_mode, status="success", duration=task_duration)
        logger.info(f"Agent任务执行完成,耗时:{task_duration:.3f}秒")
        return BaseResponse(
            code=200,
            msg="Agent任务执行成功",
            data={"collab_mode": task.collab_mode, "task_result": task_result, "task_duration": f"{task_duration:.3f}s"},
            request_id=request_id,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )
    except Exception as e:
        # 记录Agent任务执行失败指标
        task_duration = time.time() - task_start
        record_agent_task(collab_mode=task.collab_mode, status="failed", duration=task_duration)
        logger.error(f"Agent任务执行失败,耗时:{task_duration:.3f}秒,错误原因:{str(e)}", exc_info=True)
        return BaseResponse(
            code=500,
            msg=f"服务器内部错误:{str(e)[:100]}",
            data=None,
            request_id=request_id,
            timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )

# 改造其他接口(/api/v1/token/get),按同样方式添加指标记录...
(2)Agent框架核心接入监控指标(framework/core.py)

在框架任务执行逻辑中,确保指标能正确记录,同时可在从Agent执行中添加更细粒度的指标(可选):

python 复制代码
# framework/core.py 完善监控指标
class MultiAgentFramework:
    def run(self, user_task: str):
        self.logger.info(f"框架开始执行用户任务,任务描述:{user_task[:50]}...")
        try:
            # 原有执行逻辑...
            if self.collab_mode == "parallel":
                self.logger.info("采用并行协作模式,开始分发任务到所有从Agent")
                result = self._run_parallel(user_task)
            else:
                result = self._run_master_slave(user_task)
            self.logger.info("用户任务执行完成,框架返回执行结果")
            return result
        except Exception as e:
            self.logger.error(f"框架执行用户任务失败,错误原因:{str(e)}", exc_info=True)
            raise e

4. 本地测试监控指标

启动API服务后,访问http://127.0.0.1:8000/metrics,就能看到所有采集的指标,Prometheus会定时拉取这个地址的指标,本地测试时能看到指标正常输出,说明埋点成功:

bash 复制代码
# 启动API服务
python api/api_server.py
# 访问指标接口
curl http://127.0.0.1:8000/metrics

四、实战3:对接Docker+Prometheus+Grafana(可视化监控)

咱们的日志和监控已经接入框架,接下来对接Docker,让容器运行时能正常输出日志、暴露指标接口,再快速搭建Prometheus+Grafana实现指标可视化监控,这是生产级的标准搭配,2025年各大云厂商都支持一键部署。

1. 改造Dockerfile,适配日志和监控

修改根目录的Dockerfile,确保日志目录挂载、指标接口暴露,不用大改,只需要确认3点:

dockerfile 复制代码
# Dockerfile 适配日志和监控
FROM python:3.9-slim AS builder
# 原有构建逻辑不变...

FROM python:3.9-slim
WORKDIR /app
# 原有逻辑不变...

# 确认日志和数据目录创建,权限正确
RUN mkdir -p /app/logs /app/data && chmod 777 /app/logs /app/data

# 暴露API端口和指标接口端口(其实是同一个8000端口)
EXPOSE 8000

# 环境变量:确保日志和监控配置能从环境变量读取
ENV PYTHONUNBUFFERED=1
ENV LOG_LEVEL=INFO
ENV LOG_DIR=/app/logs

# 健康检查:原有逻辑不变...
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD python -c "import requests; requests.get('http://localhost:8000/health')" || exit 1

# 启动命令:运行API服务,包含日志和监控
CMD ["python", "-m", "api.api_server"]

2. 重新构建Docker镜像,运行容器

执行命令重新构建镜像,运行容器时一定要挂载日志目录,避免日志文件随容器删除而丢失:

bash 复制代码
# 重新构建镜像
docker build -t multi-agent-framework:monitor-v1.0 .

# 生产级运行容器,挂载日志和数据目录,暴露8000端口
docker run -d \
  --name agent-monitor-service \
  --restart=always \
  -p 8000:8000 \
  -v $(pwd)/logs:/app/logs \
  -v $(pwd)/data:/app/data \
  -e OPENAI_API_KEY="sk-xxx" \
  multi-agent-framework:monitor-v1.0

# 查看容器日志,确认日志正常输出
docker logs -f agent-monitor-service

3. 快速搭建Prometheus+Grafana(Docker一键部署)

用Docker Compose一键搭建Prometheus+Grafana,不用手动配置,步骤超简单:

(1)创建docker-compose.yml文件

在任意目录创建docker-compose.yml,配置Prometheus和Grafana:

yaml 复制代码
version: '3.8'
services:
  # Prometheus:指标采集和存储
  prometheus:
    image: prom/prometheus:v2.53.0  # 2025最新稳定版
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    restart: always

  # Grafana:指标可视化和告警
  grafana:
    image: grafana/grafana:10.4.0  # 2025最新稳定版
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=123456  # Grafana初始密码
    restart: always
    depends_on:
      - prometheus

volumes:
  prometheus-data:
  grafana-data:
(2)创建Prometheus配置文件(prometheus.yml)

配置Prometheus拉取Agent服务的指标,替换targets为你的Agent服务IP:端口:

yaml 复制代码
global:
  scrape_interval: 5s  # 每5秒拉取一次指标,生产环境可设为15s
  evaluation_interval: 5s

rule_files:
  - "alert_rules.yml"  # 告警规则文件(可选)

scrape_configs:
  # 采集Prometheus自身指标
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # 采集Agent框架API服务指标(核心)
  - job_name: 'multi-agent-framework'
    static_configs:
      - targets: ['你的服务器IP:8000']  # 替换为Agent服务的IP和端口
    metrics_path: '/metrics'  # 指标采集接口
    scrape_interval: 5s
(3)一键启动Prometheus+Grafana
bash 复制代码
# 启动服务
docker-compose up -d

# 查看服务状态
docker-compose ps
(4)Grafana可视化配置
  1. 访问Grafana:http://你的服务器IP:3000,账号admin,密码123456(配置文件中设置的);
  2. 添加数据源:选择Prometheus,地址填http://prometheus:9090,保存;
  3. 导入仪表盘:可导入Python/FastAPI通用仪表盘(ID:12900),或自定义仪表盘,添加咱们的Agent指标(如agent_api_request_totalagent_task_duration),实现可视化监控。

五、生产级实战技巧:日志排查+监控告警

1. 日志排查核心技巧(快速定位问题)

  1. 按request_id排查 :调用方反馈问题时,让其提供响应头的X-Request-ID,按该ID搜索日志,直接定位整个请求链路;
  2. 按日志级别排查:先看ERROR/CRITICAL日志,快速找到错误点,再看INFO/DEBUG日志补充上下文;
  3. 按模块名排查 :日志名包含模块(如api.run_agentagent.slave.search),定位问题出在API层还是Agent层;
  4. 使用日志检索工具:生产环境不要手动翻日志文件,用ELK/PLG栈(Elasticsearch+Logstash+Kibana)做日志检索,支持模糊搜索、按时间筛选。

2. 监控告警核心技巧(提前发现异常)

  1. 配置核心告警规则:在Prometheus中配置告警规则(如API错误率>5%、接口P95响应时间>3s、CPU使用率>80%持续5分钟);
  2. 配置告警接收方式:Grafana对接钉钉/企业微信/邮件/短信,告警触发时自动推送;
  3. 设置仪表盘大屏:在公司监控室挂Grafana大屏,核心指标(QPS、错误率、响应时间、资源占用)一目了然;
  4. 做指标趋势分析:通过Grafana查看指标趋势,比如QPS随时间的变化,提前做好扩容准备。

六、实战总结

这篇咱们给多Agent框架+API服务搭建了生产级的日志系统和监控体系,实现了服务的"可观测、可排查、可监控",核心成果如下:

  1. 搭建了分级日志系统,实现日志分级、链路追踪、文件轮转,出问题时能通过request_id快速定位根因,再也不用瞎猜;
  2. 添加了核心监控指标埋点,覆盖API服务和Agent框架的所有关键维度,能实时掌握服务的QPS、响应时间、资源占用、任务执行情况;
  3. 无缝对接Docker+Prometheus+Grafana,实现了容器化运行+指标采集+可视化监控,达到工业级生产标准;
  4. 所有配置都从环境变量读取,支持Docker动态修改,不用改代码,部署超方便。

到这里,咱们的多Agent框架已经完成了开发→优化→打包→部署→API封装→监控日志 的全流程改造,从一个本地脚本变成了可对外提供服务、可跨系统调用、可监控、可排查的生产级AI服务,能真正7×24小时稳定运行在生产环境,为业务创造价值~


目前国内还是很缺AI人才的,希望更多人能真正加入到AI行业,共同促进行业进步。想要系统学习AI知识的朋友可以看看我的教程http://blog.csdn.net/jiangjunshow,教程通俗易懂,风趣幽默,从深度学习基础原理到各领域实战应用都有讲解。

相关推荐
A尘埃2 小时前
数值特征标准化StandardScaler和类别不平衡SMOTE
人工智能·深度学习·机器学习
来两个炸鸡腿2 小时前
【Datawhale组队学习202601】Base-NLP task06 大模型训练与量化
人工智能·学习·自然语言处理
bylander2 小时前
【AI学习】TM Forum自智网络L4级标准体系
人工智能·学习·智能体·自动驾驶网络
世优科技虚拟人2 小时前
从AI数字人讲解到MR数字人导览,数字人厂商革新文旅新服务
人工智能·大模型·数字人·智能交互
2301_817497332 小时前
自然语言处理(NLP)入门:使用NLTK和Spacy
jvm·数据库·python
张小凡vip2 小时前
数据挖掘(七) ---Jupyter Notebook快捷方式和魔术命令(特殊命令)
人工智能·jupyter·数据挖掘
Luhui Dev2 小时前
MCP、Skills、Agents SDK 什么区别?AI 能力调度接口的 3 种范式解析
人工智能
weixin_550083152 小时前
QTdesigner配置在pycharm里使用anaconda环境配置安装成功
ide·python·pycharm
才兄说2 小时前
机器人租售出场稳?到点就上台
人工智能·机器人