AI Agent执行链路的可观测性:日志、指标与追踪的完整方案

关键词:AI Agent可观测性、分布式追踪、执行链路监控、LLM应用日志、Agent指标体系、OpenTelemetry、可观测性实践

摘要:随着AI Agent在企业服务、智能客服、自动化办公等场景的规模化落地,执行链路黑盒问题已经成为阻碍Agent迭代优化的核心瓶颈:用户反馈答非所问时无法定位是上下文串扰、LLM推理偏差还是工具调用错误,成本超支时无法追溯令牌消耗的具体分布,响应超时无法判断瓶颈在LLM限流还是第三方服务故障。本文以生活中外卖配送的类比深入浅出地讲解可观测性三大核心概念,结合AI Agent的独有特性,从日志、指标、追踪三个维度构建完整的全链路可观测方案,提供开箱即用的Python代码实现、系统架构设计、最佳实践和未来趋势分析,帮助开发者彻底解决Agent链路排查难、优化无依据的痛点。


背景介绍

目的和范围

本文的核心目标是提供一套可直接落地的AI Agent执行链路可观测性方案,覆盖从用户请求进入Agent到最终响应返回的全流程,支持单Agent、多Agent协作、Agent调用第三方工具/LLM/其他Agent的所有场景。本方案聚焦于Agent应用层的执行链路监控,不覆盖底层GPU算力监控、LLM模型内部推理过程监控等基础设施层面的内容,所有实现均兼容主流的可观测性开源生态,无需重复造轮子。

预期读者

本文适合所有AI应用相关的从业者:

  1. LLM应用/Agent开发工程师:学习如何给Agent埋点、排查链路故障
  2. SRE/运维工程师:了解如何搭建Agent专属的可观测平台
  3. AI产品经理:理解可观测性如何支撑产品体验优化和成本控制
  4. 技术负责人:掌握Agent规模化落地的核心运维能力建设路径

文档结构概述

本文将按照从概念到实战的路径逐步展开:首先用生活化的类比讲解核心概念,然后梳理三大可观测支柱的关系和对比,接着讲解核心算法原理和数学模型,之后提供完整的项目实战代码和系统架构设计,最后介绍实际应用场景、最佳实践和未来发展趋势。

术语表

核心术语定义
  1. AI Agent执行链路:从用户输入请求开始,到Agent感知、LLM推理、工具调用、决策生成、响应返回的全流程步骤
  2. 可观测性三大支柱:日志(事件的详细记录)、指标(事件的聚合统计值)、追踪(单个请求的全链路轨迹)
  3. Trace(追踪):单个请求的完整执行链路,由多个Span(步骤节点)组成,每个Trace有全局唯一的TraceID
  4. Span(跨度):Trace中的单个执行步骤,记录该步骤的开始/结束时间、状态、属性等信息
  5. 令牌消耗:LLM调用过程中输入和输出文本对应的Token总数,是LLM成本的核心计算依据
缩略词列表
缩略词 全称 含义
OTel OpenTelemetry CNCF主导的可观测性统一标准,支持日志、指标、追踪的统一采集和上报
APM Application Performance Monitoring 应用性能监控
LLM Large Language Model 大语言模型
RAG Retrieval Augmented Generation 检索增强生成
OTLP OpenTelemetry Protocol OpenTelemetry的统一数据传输协议

核心概念与联系

故事引入

我们可以把AI Agent的执行链路类比成大家熟悉的外卖配送流程:
你在APP上下单点了一份小龙虾(用户输入请求),平台把订单派给商家(Agent接收请求),商家收到订单后先看你有没有备注忌口(解析用户意图),发现你要加辣但厨房没辣椒了,就给菜市场打电话送辣椒(调用第三方工具/LLM),辣椒送到后厨师炒菜(LLM推理生成响应),炒完后装盒交给骑手(输出响应),骑手送到你家(返回给用户)。
如果最后你等了2小时才收到餐,你打开外卖APP就能看到每个节点的时间:商家10分钟才接单,菜市场送辣椒花了40分钟,厨师炒菜花了20分钟,骑手堵在路上花了50分钟——这就是可观测性的价值。如果没有这个链路,你根本不知道是商家慢、骑手慢还是菜市场出了问题,想投诉都找不到对象。
现在大部分AI Agent就是没有这个配送轨迹的外卖平台:用户反馈响应慢,你不知道是LLM推理慢、工具调用超时还是代码写得有问题;用户反馈答非所问,你不知道是上下文串了、工具返回了错误数据还是LLM自己抽风。

核心概念解释(小白也能懂)

核心概念一:日志(Log)

日志就相当于外卖每个节点的拍照留证:商家10:00接单拍了一张订单截图,10:10炒完菜拍了一张小龙虾的照片,10:15骑手取餐拍了一张餐品的照片。每一条日志都是单个事件的完整记录,包含时间、事件内容、相关属性等信息。
对于AI Agent来说,日志就是每个执行步骤的详细记录:比如"2024-05-20 12:00:00 用户ID=123 调用GPT-3.5-turbo 输入=‘今天北京天气’ 输出=‘北京今天晴 25度’ 消耗令牌120",当你要排查单个用户的问题时,直接搜索对应用户的日志就能看到完整的事件详情。

核心概念二:指标(Metric)

指标就相当于外卖平台的统计报表:这个商家平均出餐时间15分钟,超时率2%,这个骑手平均配送时间30分钟,好评率98%。指标是多个事件的聚合统计值,都是数值型数据,方便看整体趋势和做告警。
对于AI Agent来说,指标就是全量请求的统计数据:比如LLM的P95响应时间是1200ms,工具调用成功率是99.2%,每小时令牌消耗是100万,用户请求平均响应时间是1500ms。当你要监控整体服务质量、做成本分析时,看指标就够了。

核心概念三:追踪(Trace)

追踪就相当于你外卖APP里的配送轨迹:从你下单到收到餐的每个节点按时间串起来,有一个唯一的订单号关联所有节点。每个Trace有全局唯一的TraceID,把同一个请求的所有执行步骤(Span)串起来,你可以看到整个请求每个步骤花了多长时间、有没有出错。
对于AI Agent来说,Trace就是单个用户请求的完整执行链路:比如TraceID=abc123的请求,总耗时1500ms,其中Agent接收请求花了100ms,调用LLM花了800ms,调用搜索工具花了400ms,生成响应花了200ms。当你要排查单个请求的性能瓶颈、跨服务调用故障时,Trace是最有效的工具。

核心概念之间的关系

三大支柱是相辅相成的关系,缺了任何一个都没法完整监控Agent的执行链路:

  1. 日志是点,追踪是线,指标是面:日志记录单个事件的详情,追踪把同一个请求的多个事件串成完整的链路,指标把所有请求的事件聚合成整体的趋势。
  2. 排查问题的标准流程是:先看指标发现异常(比如响应超时率从0.1%涨到5%),再用追踪找到异常请求的链路瓶颈(比如搜索工具调用耗时从200ms涨到2000ms),最后用日志看这个工具调用的详细错误信息(比如搜索服务返回500错误)
核心概念属性对比
对比维度 日志 指标 追踪
数据粒度 事件级,单事件完整信息 聚合级,多事件统计值 链路级,单请求全流程信息
存储成本 高,单条可达KB级 低,单条仅为数值+标签 中,单链路包含多个Span
查询速度 慢,需扫描大量数据 快,预聚合数值查询 中,按TraceID精准查询
核心用途 排查单个问题的根因 监控整体趋势、告警 排查单请求链路瓶颈
典型示例 “用户123调用LLM消耗令牌120” “llm.response.time.p95=1200ms” “Trace abc123总耗时1500ms,LLM占800ms”

概念实体关系(ER图)

发起

对应

包含

产生

上报

可能包含

可能包含

USER

AGENT_REQUEST

string

request_id

string

user_id

string

user_input

string

response

datetime

create_time

TRACE

string

trace_id

int

total_duration

string

status

SPAN

string

span_id

string

parent_span_id

string

span_name

int

duration

string

status

LOG

string

log_id

string

level

string

content

map

attributes

datetime

timestamp

METRIC

string

metric_name

float

value

map

labels

datetime

timestamp

LLM_CALL

string

model

int

prompt_tokens

int

completion_tokens

int

total_tokens

TOOL_CALL

string

tool_name

string

input

string

output

bool

success

可观测系统整体架构图

用户端

Agent服务集群

OTel SDK埋点

OTel Collector

Loki 日志存储

Prometheus 指标存储

Jaeger 追踪存储

Grafana 统一可视化

告警平台

根因分析平台

企业微信/钉钉/邮件

单请求执行链路可观测流程图

收到用户请求

生成全局唯一TraceID

创建根Span agent.request

记录用户请求日志

调用LLM推理

创建子Span llm.call

记录LLM输入日志

执行LLM调用

记录LLM输出、令牌消耗指标、响应时延指标

结束Span llm.call

是否需要调用工具

创建子Span tool.call

记录工具输入日志

执行工具调用

记录工具输出、调用成功率指标、耗时指标

结束Span tool.call

生成最终响应

记录响应日志

结束根Span agent.request

返回响应给用户


核心算法原理 & 数学模型

核心算法原理

AI Agent可观测性的核心算法是全链路上下文透传:从用户请求进入Agent的第一时间生成全局唯一的TraceID,之后所有的LLM调用、工具调用、跨Agent调用都要携带这个TraceID,每个步骤生成的日志、指标都要绑定这个TraceID,这样就能把同一个请求的所有数据关联起来。
核心实现逻辑是用装饰器/中间件对Agent的所有核心步骤做埋点,自动生成Span、记录日志、上报指标,无需业务代码侵入。

数学模型 & 公式讲解

我们可以用数学公式量化Agent的核心可观测指标:

  1. LLM平均响应时延:统计周期内所有LLM调用的平均耗时,单位毫秒
    T l l m _ a v g = ∑ i = 1 n ( T l l m _ e n d i − T l l m _ s t a r t i ) n T_{llm\_avg} = \frac{\sum_{i=1}^{n} (T_{llm\_end_i} - T_{llm\_start_i})}{n} Tllm_avg=ni=1n(Tllm_endiTllm_starti)
    其中 T l l m _ s t a r t i T_{llm\_start_i} Tllm_starti是第i次LLM调用的开始时间, T l l m _ e n d i T_{llm\_end_i} Tllm_endi是结束时间,n是统计周期内的LLM调用次数。
  2. 工具调用成功率:统计周期内工具调用成功的比例,单位%
    S t o o l = N t o o l _ s u c c e s s N t o o l _ t o t a l × 100 % S_{tool} = \frac{N_{tool\_success}}{N_{tool\_total}} \times 100\% Stool=Ntool_totalNtool_success×100%
    其中 N t o o l _ s u c c e s s N_{tool\_success} Ntool_success是成功调用次数, N t o o l _ t o t a l N_{tool\_total} Ntool_total是总调用次数。
  3. 令牌消耗速率:统计周期内平均每秒钟消耗的令牌数量,用于成本监控
    R t o k e n = ∑ i = 1 n K i T p e r i o d R_{token} = \frac{\sum_{i=1}^{n} K_{i}}{T_{period}} Rtoken=Tperiodi=1nKi
    其中 K i K_i Ki是第i次LLM调用消耗的总令牌数, T p e r i o d T_{period} Tperiod是统计周期的总秒数。
  4. 请求成功率:统计周期内Agent正常处理请求的比例
    S r e q u e s t = N r e q _ s u c c e s s N r e q _ t o t a l × 100 % S_{request} = \frac{N_{req\_success}}{N_{req\_total}} \times 100\% Srequest=Nreq_totalNreq_success×100%
    其中 N r e q _ s u c c e s s N_{req\_success} Nreq_success是正常返回的请求数, N r e q _ t o t a l N_{req\_total} Nreq_total是总请求数。

项目实战:完整可观测方案实现

开发环境搭建

我们使用主流的开源可观测栈,所有工具都是免费开源的:

  1. 开发环境:Python 3.10+
  2. 采集层:OpenTelemetry SDK 1.24+
  3. 采集转发:OTel Collector 0.98+
  4. 存储层:Loki(日志)、Prometheus(指标)、Jaeger(追踪)
  5. 可视化层:Grafana 10.0+
依赖安装
# 安装Python依赖
pip install langchain openai opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp opentelemetry-instrumentation-requests python-dotenv
# 启动可观测服务(用Docker Compose一键启动)
wget https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector-contrib/main/examples/demo/docker-compose.yaml
docker-compose up -d

启动后访问以下地址验证服务:

  • Grafana:http://localhost:3000 (默认账号密码admin/admin)
  • Jaeger:http://localhost:16686
  • Prometheus:http://localhost:9090

完整代码实现

import os
import time
from dotenv import load_dotenv
from opentelemetry import trace, metrics, logs
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.logs import LogEmitterProvider
from opentelemetry.sdk.logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.http.log_exporter import OTLPLogExporter
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.trace.status import StatusCode
from langchain.agents import initialize_agent, Tool
from langchain.llms import OpenAI
from langchain.tools import DuckDuckGoSearchRun

# 加载环境变量
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OTEL_ENDPOINT = os.getenv("OTEL_ENDPOINT", "http://localhost:4318")

# ====================== 1. 初始化OTel可观测组件 ======================
# 初始化追踪
trace.set_tracer_provider(TracerProvider())
tracer_provider = trace.get_tracer_provider()
tracer_provider.add_span_processor(
    BatchSpanProcessor(OTLPSpanExporter(endpoint=f"{OTEL_ENDPOINT}/v1/traces"))
)
tracer = trace.get_tracer("ai-agent-observability")

# 初始化指标
metric_reader = PeriodicExportingMetricReader(
    OTLPMetricExporter(endpoint=f"{OTEL_ENDPOINT}/v1/metrics")
)
metrics.set_meter_provider(MeterProvider(metric_readers=[metric_reader]))
meter = metrics.get_meter("ai-agent-observability")
# 定义核心指标
llm_response_time = meter.create_histogram(
    "llm.response.time",
    description="LLM响应时间,单位毫秒",
    unit="ms"
)
tool_call_success = meter.create_counter(
    "tool.call.success",
    description="工具调用成功次数"
)
tool_call_failure = meter.create_counter(
    "tool.call.failure",
    description="工具调用失败次数"
)
token_usage_total = meter.create_counter(
    "token.usage.total",
    description="总令牌消耗数量"
)
request_total = meter.create_counter(
    "agent.request.total",
    description="总请求次数"
)

# 初始化日志
logs.set_log_emitter_provider(LogEmitterProvider())
log_emitter_provider = logs.get_log_emitter_provider()
log_emitter_provider.add_log_record_processor(
    BatchLogRecordProcessor(OTLPLogExporter(endpoint=f"{OTEL_ENDPOINT}/v1/logs"))
)
logger = logs.get_log_emitter("ai-agent-observability")

# 自动埋点所有HTTP请求
RequestsInstrumentor().instrument()

# ====================== 2. 埋点装饰器(无侵入式埋点) ======================
def observe_span(span_name, attributes=None):
    def decorator(func):
        def wrapper(*args, **kwargs):
            # 获取当前上下文的TraceID
            current_span = trace.get_current_span()
            trace_id = format(current_span.get_span_context().trace_id, "016x") if current_span.is_recording() else "unknown"
            # 启动新的Span
            with tracer.start_as_current_span(span_name, attributes=attributes or {}) as span:
                # 注入公共属性
                span.set_attribute("user_id", kwargs.get("user_id", "unknown"))
                span.set_attribute("trace_id", trace_id)
                start_time = time.time()
                try:
                    result = func(*args, **kwargs)
                    span.set_status(StatusCode.OK)
                    return result
                except Exception as e:
                    span.set_status(StatusCode.ERROR)
                    span.record_exception(e)
                    # 记录错误日志
                    logger.emit(
                        logs.SeverityNumber.ERROR,
                        f"{span_name}执行失败: {str(e)}",
                        attributes={
                            "trace_id": trace_id,
                            "user_id": kwargs.get("user_id", "unknown"),
                            "error": str(e)
                        }
                    )
                    raise
                finally:
                    # 记录耗时
                    duration_ms = (time.time() - start_time) * 1000
                    span.set_attribute("duration_ms", duration_ms)
        return wrapper
    return decorator

# ====================== 3. 核心功能埋点 ======================
@observe_span("llm.call", attributes={"type": "llm"})
def call_llm(prompt, model="gpt-3.5-turbo", user_id="unknown"):
    llm = OpenAI(model_name=model, temperature=0, openai_api_key=OPENAI_API_KEY)
    # 记录LLM输入日志
    logger.emit(
        logs.SeverityNumber.INFO,
        "开始调用LLM",
        attributes={
            "prompt": prompt,
            "model": model,
            "user_id": user_id,
            "trace_id": format(trace.get_current_span().get_span_context().trace_id, "016x")
        }
    )
    # 执行LLM调用
    response = llm.generate([prompt])
    # 记录令牌消耗
    usage = response.llm_output.get("token_usage", {})
    total_tokens = usage.get("total_tokens", 0)
    prompt_tokens = usage.get("prompt_tokens", 0)
    completion_tokens = usage.get("completion_tokens", 0)
    token_usage_total.add(total_tokens, attributes={
        "model": model,
        "user_id": user_id
    })
    # 记录响应时间指标
    llm_response_time.record(
        (time.time() - start_time) * 1000,
        attributes={"model": model, "user_id": user_id}
    )
    # 记录LLM输出日志
    logger.emit(
        logs.SeverityNumber.INFO,
        "LLM调用完成",
        attributes={
            "response": response.generations[0][0].text,
            "total_tokens": total_tokens,
            "prompt_tokens": prompt_tokens,
            "completion_tokens": completion_tokens,
            "model": model,
            "user_id": user_id,
            "trace_id": format(trace.get_current_span().get_span_context().trace_id, "016x")
        }
    )
    return response.generations[0][0].text

@observe_span("tool.call.search", attributes={"type": "tool", "tool_name": "duckduckgo_search"})
def call_search(query, user_id="unknown"):
    search = DuckDuckGoSearchRun()
    # 记录工具输入日志
    logger.emit(
        logs.SeverityNumber.INFO,
        "开始调用搜索工具",
        attributes={
            "query": query,
            "user_id": user_id,
            "trace_id": format(trace.get_current_span().get_span_context().trace_id, "016x")
        }
    )
    try:
        result = search.run(query)
        tool_call_success.add(1, attributes={"tool": "search", "user_id": user_id})
        # 记录工具输出日志
        logger.emit(
            logs.SeverityNumber.INFO,
            "搜索工具调用完成",
            attributes={
                "result_length": len(result),
                "user_id": user_id,
                "trace_id": format(trace.get_current_span().get_span_context().trace_id, "016x")
            }
        )
        return result
    except Exception as e:
        tool_call_failure.add(1, attributes={"tool": "search", "user_id": user_id, "error": str(e)})
        raise

# ====================== 4. Agent初始化 ======================
tools = [
    Tool(
        name="Search",
        func=call_search,
        description="当你需要回答实时信息、未知问题或者最近的事件时使用这个工具"
    )
]
llm = OpenAI(model_name="gpt-3.5-turbo", temperature=0, openai_api_key=OPENAI_API_KEY)
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)

# ====================== 5. 请求入口埋点 ======================
@observe_span("agent.request", attributes={"type": "request"})
def process_user_request(user_input, user_id):
    request_total.add(1, attributes={"user_id": user_id})
    trace_id = format(trace.get_current_span().get_span_context().trace_id, "016x")
    # 记录请求日志
    logger.emit(
        logs.SeverityNumber.INFO,
        "收到用户请求",
        attributes={
            "user_input": user_input,
            "user_id": user_id,
            "trace_id": trace_id
        }
    )
    # 执行Agent逻辑
    response = agent.run(user_input)
    # 记录响应日志
    logger.emit(
        logs.SeverityNumber.INFO,
        "返回用户响应",
        attributes={
            "response": response,
            "user_id": user_id,
            "trace_id": trace_id
        }
    )
    return response, trace_id

# 测试
if __name__ == "__main__":
    user_input = "2024年北京五一假期的平均气温是多少?"
    user_id = "test_user_001"
    response, trace_id = process_user_request(user_input, user_id)
    print(f"TraceID: {trace_id}")
    print(f"响应: {response}")

代码解读

  1. OTel初始化部分:统一初始化日志、指标、追踪的采集器,所有数据通过OTLP协议上报到OTel Collector,无需对接多个存储的SDK。
  2. 埋点装饰器:通用的无侵入埋点装饰器,自动创建Span、记录耗时、上报错误日志,业务代码只需要加个装饰器就能完成埋点。
  3. 核心功能埋点:对LLM调用、工具调用分别做埋点,记录所有核心属性(令牌消耗、模型类型、工具名称等)。
  4. 请求入口埋点:用户请求进入时生成根Span,所有子步骤的Span都关联这个根Span的TraceID,实现全链路关联。

实际应用场景

场景1:多Agent协作故障排查

某企业的客服Agent由三个Agent组成:意图识别Agent、知识库Agent、应答生成Agent,用户反馈某个问题一直返回错误。运维人员通过Grafana指标发现知识库Agent的请求失败率涨到30%,点击指标峰值跳转到对应的Trace列表,找到失败请求的TraceID,通过Trace看到知识库Agent调用RAG检索工具时返回了500错误,再查看对应日志发现是RAG服务的向量数据库磁盘满了,10分钟就定位解决了问题,如果没有可观测性,可能要排查几个小时。

场景2:成本优化

某SaaS公司的Agent服务每月LLM成本超过100万,通过令牌消耗指标分析发现,40%的令牌消耗来自用户重复提问的相同问题,于是他们给相同问题的响应加了缓存,每月成本直接降了35万;另外发现15%的令牌消耗来自GPT-4调用,但其中80%的请求用GPT-3.5就能满足,于是做了模型路由,成本又降了10万,总共成本降了45%。

场景3:体验优化

某C端Agent产品的用户平均响应时间是3秒,留存率只有20%,通过Trace分析发现60%的耗时来自搜索工具调用,于是他们给常用搜索结果加了缓存,平均响应时间降到1.2秒,留存率涨到35%,收入直接涨了70%。

最佳实践Tips

  1. TraceID全链路透传:从用户请求进入的第一时间生成TraceID,所有跨进程、跨服务调用都要在Header里携带TraceID,避免链路断裂。
  2. 结构化日志优先:所有日志都要用结构化格式(JSON),不要打非结构化的文本,方便查询和关联TraceID。
  3. 指标多维度标签:指标要加上模型类型、工具名称、用户ID、业务场景等标签,方便下钻分析。
  4. 分层采样策略:错误请求、慢请求全采样,正常请求按10%的比例采样,平衡存储成本和排查需求。
  5. 关联跳转:Grafana仪表盘要配置关联跳转,点击指标可以跳转到对应Trace列表,点击Trace可以跳转到对应日志,实现一键排查。

未来发展趋势与挑战

发展历史

时间 阶段 可观测需求 典型方案
2020年及以前 LLM API调用阶段 监控LLM可用性、时延、成功率 普通HTTP监控
2021-2022年 单Agent阶段 监控思考过程、工具调用、令牌消耗 自定义埋点、LangSmith等专用工具
2023年 多Agent协作阶段 分布式链路追踪、上下文监控 引入OpenTelemetry分布式追踪
2024年及以后 Agent规模化落地阶段 全链路可观测、智能根因分析、自愈 统一可观测平台、AIOps结合

核心挑战

  1. 多Agent分布式上下文关联:跨节点、跨集群的Agent调用如何透传上下文,避免TraceID丢失。
  2. LLM推理黑盒可观测:目前只能看到LLM的输入输出,无法监控内部推理过程,如何判断是模型偏差还是输入错误。
  3. 高并发下的采样策略:Agent流量大的时候全量采集成本太高,如何采样既不影响故障排查又能控制成本。

未来趋势

  1. 可观测性驱动开发(ODD):开发Agent的时候就同步埋点,用可观测数据指导迭代优化,而不是出了问题才补监控。
  2. 智能根因分析:结合AIOps自动分析可观测数据,直接给出故障根因和解决方案,无需人工排查。
  3. 统一标准:未来会有统一的AI Agent可观测性标准,所有Agent框架都会原生支持OTel埋点,无需手动开发。

总结:学到了什么?

核心概念回顾

  1. 日志:单个事件的详细记录,用于排查问题根因。
  2. 指标:多事件的聚合统计值,用于监控整体趋势和告警。
  3. 追踪:单个请求的全链路轨迹,用于排查性能瓶颈。

概念关系回顾

三大支柱相辅相成,排查问题的标准流程是:先看指标发现异常,再用追踪定位链路瓶颈,最后用日志确认根因。

思考题:动动小脑筋

  1. 如果你正在开发一个AI客服Agent,你会优先埋哪三个核心指标?为什么?
  2. 多Agent协作的时候,如果某个请求的TraceID丢失了,你会怎么排查链路断裂的原因?

附录:常见问题与解答

Q1:全量采集可观测数据会不会影响Agent的性能?

A:不会,我们用的是异步上报,不会阻塞主链路,而且可以通过采样策略控制采集量,对性能的影响小于1%。

Q2:是不是一定要用OpenTelemetry?能不能自己写埋点?

A:小项目可以自己写埋点,大项目推荐用OTel,它是行业标准,兼容所有主流的可观测工具,不用重复造轮子,也方便和现有APM系统打通。

Q3:日志、指标、追踪三个缺一不可吗?

A:是的,缺了任何一个都会导致排查问题的链路断裂:只有指标你知道有异常但不知道为什么,只有追踪你知道某个请求慢但不知道整体的影响范围,只有日志你查问题像大海捞针。

扩展阅读 & 参考资料

  1. OpenTelemetry官方文档
  2. LangSmith官方文档
  3. Grafana LLM可观测方案
  4. 《可观测性工程》(O’Reilly出版)
  5. CNCF AI可观测性白皮书
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐