跳转到内容

05 - 可观测性系统:Callback + Instrumentation

05 - 可观测性系统:Callback + Instrumentation

学习目标

本章将带你分析 LlamaIndex 的可观测性系统。你将学到:

  • 双层架构设计(CallbackManager + Instrumentation)
  • CallbackManager 的多 handler 注册机制
  • Instrumentation 的 dispatcher → handler → span 三层架构
  • 自动 span 追踪(LLM 调用、工具调用、检索操作)
  • 性能 overhead 与生产环境的使用建议

项目实践

双层架构

LlamaIndex 的可观测性系统由两层组成:

Instrumentation(底层):自动为每个操作创建 span,通过 dispatcher 推送给 handler。无需手动调用。

CallbackManager(高层):在关键操作的入口和出口触发回调事件,需要手动注册 handler。

CallbackManager 多 Handler 注册

CallbackManager 支持注册多个 handler,每个 handler 监听不同的事件:

from llama_index.core.callbacks import CallbackManager
from llama_index.core.callbacks.global_handlers import set_global_handler
# 注册调试 handler(打印所有事件)
from llama_index.core.callbacks import LlamaDebugHandler
callback_manager = CallbackManager(handlers=[LlamaDebugHandler()])
# 注册 token 计数 handler
from llama_index.core.callbacks import TokenCountingHandler
callback_manager.add_handler(TokenCountingHandler())

每个 handler 实现特定的回调方法:

class BaseCallbackHandler:
def on_event_start(self, event_type, payload): ...
def on_event_end(self, event_type, payload): ...
def on_llm_start(self, ...): ...
def on_llm_end(self, ...): ...
def on_tool_start(self, ...): ...
def on_tool_end(self, ...): ...

Instrumentation 的三层架构

Instrumentation 模块使用 dispatcher → handler → span 三层架构:

# Dispatcher: 事件分发器,将 span 推送给注册的 handlers
# SpanHandler: 处理 span 事件(如打印、发送到 OpenTelemetry)
# OpenTelemetryHandler: 发送到 OpenTelemetry 后端

每个 LLM 调用、工具调用、检索操作自动创建 span:

自动 Span 追踪

以下操作自动创建 span,无需手动添加:

操作Span 名称包含信息
LLM 调用llm.chat / llm.complete模型名称、prompt、响应
工具调用tool.call工具名、参数、结果
检索retriever.retrieve查询、返回节点数
嵌入embedding.embed模型名称、文本数量
响应合成response.synthesize模式(refine/tree_summarize)

性能 Overhead

重要配置:在 llama-index-core/pyproject.toml 的 coverage 配置中,Instrumentation 和 Workflow 被排除在覆盖率统计之外:

[tool.coverage.run]
omit = [
"llama_index/core/instrumentation/*",
"llama_index/core/workflow/*",
]

这说明 Instrumentation 模块的 overhead 较大——它通过装饰器和上下文管理器在每个操作入口/出口执行额外代码。

生产环境建议

环境推荐配置
开发调试启用所有 CallbackHandler + Instrumentation
测试环境仅启用 TokenCountHandler(轻量)
生产环境仅启用 OpenTelemetryHandler(批量发送)或禁用

问题与规避

陷阱对策
Instrumentation overhead 导致延迟增加生产环境使用 OpenTelemetryHandler 批量发送,或完全禁用
Callback handler 抛异常导致操作中断在 handler 的回调方法中捕获所有异常,不要向上抛出
多 handler 注册时事件重复触发理解 CallbackManager 和 Instrumentation 是两个独立的系统,避免重复注册
TokenCountHandler 计数不准确确保 tokenizer 与 LLM 实际使用的 tokenizer 一致

设计取舍

Callback vs Instrumentation

维度CallbackManagerInstrumentation
触发方式手动注册,自动触发自动注册,自动触发
灵活性高(可选择性注册 handler)低(全局启用/禁用)
性能中(取决于 handler 数量)高(overhead 较大)
集成自定义 Python handler支持 OpenTelemetry 标准
耦合度低(handler 可独立开发)高(dispatcher 嵌入核心代码)

双层架构的原因:CallbackManager 提供轻量、灵活的自定义回调;Instrumentation 提供标准化的 span 追踪(支持 OpenTelemetry)。两者互补而非替代。

参考来源

  • LlamaIndex CallbackManager 源码:llama-index-core/llama_index/core/callbacks/
  • LlamaIndex Instrumentation 源码:llama-index-core/llama_index/core/instrumentation/