[Bug]: OTel v2 GenAI exception events are never exported — Event body defaults to None, and the OTLP encoder drops the whole batch

当 LiteLLM 开启 OTel v2( LITELLM_OTEL_V2=true )并启用事件导出时, gen_ai.client.operation.exception 事件因 Event.body 默认为 None ,导致 OTLP 编码器在序列化时抛异常,整批日志被静默丢弃。排查重点是 v

快速结论:当 LiteLLM 开启 OTel v2(LITELLM_OTEL_V2=true)并启用事件导出时,gen_ai.client.operation.exception 事件因 Event.body 默认为 None,导致 OTLP 编码器在序列化时抛异常,整批日志被静默丢弃。排查重点是 v2 事件路径与 OTLP 编码器,而不是 v1 的 opentelemetry.py。

适用环境:LiteLLM 代理部署;已确认的依赖为 LiteLLM 硬锁定的 opentelemetry-api/-sdk/-exporter-otlp==1.28.0;导出协议为 OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf。Issue 未提供操作系统、Python、CUDA、显卡信息。

最快修复方案:Issue 中作者验证有效的修复是:在 litellm/integrations/otel/plumbing/events.py 的 record_operation_exception 中,为 Event 传入 body=message(异常消息本身已在 exception.message 中)。该修复已由 #42431 合并落地。

注意事项:依赖升级到 opentelemetry-exporter-otlp-proto-common>=1.43.0 虽然从版本层面能避开 None 编码异常,但 LiteLLM 当前硬锁定 1.28.0,单纯升版本与仓库约束冲突;且原 Issue 明确指出这不是推荐的修复路径。修复前所有该 pipeline 上的日志批次都会丢失,不只是异常事件。

问题场景

用户运行 LiteLLM 代理,并通过 litellm_settings.callbacks: ["otel"] 启用 OTel 回调,同时开启 v2 集成与事件导出:

LITELLM_OTEL_V2=true
LITELLM_OTEL_INTEGRATION_ENABLE_EVENTS=true
OTEL_EXPORTER_OTLP_ENDPOINT=http://<collector>
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

在这种配置下,所有 gen_ai.client.operation.exception 事件都不会出现在 OTLP collector 侧,且与被一同批处理的日志记录一起被丢弃。

报错原文

Exception while exporting logs.
  .../opentelemetry/sdk/_logs/_internal/export/__init__.py line 307, in _export_batch
  .../opentelemetry/exporter/otlp/proto/http/_log_exporter/__init__.py line 159, in export
    serialized_data = encode_logs(batch).SerializeToString()
  .../opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py line 57, in _encode_log
    body=_encode_value(log_data.log_record.body),
  .../opentelemetry/exporter/otlp/proto/common/_internal/__init__.py line 90, in _encode_value
    raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None

原因分析

最可能的原因是:GenAIEventRecorder.record_operation_exception(位于 litellm/integrations/otel/plumbing/events.py)在构造 Event 时没有传 body。而 opentelemetry._events.Event.body 默认是 None,OTLP 的 AnyValue 没有 None 的表示方式,于是 _encode_value 在序列化整批日志时抛异常。

更关键的是数据丢失机制:BatchLogRecordProcessor._export_batch 捕获异常后清空本批记录并返回 idx,将这批数据当作已成功导出处理,因此不会重试、不崩溃,只在日志里留下 traceback。由于 record_operation_exception 是 v2 logs signal 上唯一的 emit 点,该 pipeline 上的每一批都包含不可编码记录,最终 logs signal 什么都发不出去。

Issue 还确认:上游 OTel 在 opentelemetry-exporter-otlp-proto-common 1.43.0 中为 _encode_value 增加了 None 分支(if value is None: return PB2AnyValue()),但从 1.28.0 到 1.42.1 都会抛异常;LiteLLM 硬锁 1.28.0,所以按发布版本该事件永远无法导出。现有 CI 未发现该问题,是因为测试都用 InMemoryLogExporter,从不经过真正的 OTLP 编码器。

环境排查

  • 确认是否设置了 LITELLM_OTEL_V2=true,即问题是否出现在 v2 集成路径而非 v1 opentelemetry.py。
  • 确认是否设置了 LITELLM_OTEL_INTEGRATION_ENABLE_EVENTS=true,事件导出是否开启。
  • 确认 OTEL_EXPORTER_OTLP_PROTOCOL 是否为 http/protobuf(即是否会触发 OTLP 编码器)。
  • 确认 litellm_settings.callbacks 中是否包含 otel。
  • 确认安装的 opentelemetry-api / opentelemetry-sdk / opentelemetry-exporter-otlp 版本;Issue 中 LiteLLM 锁定为 1.28.0,1.42.1 及以下同样会触发该编码异常。
  • 检查日志中是否存在上述 Exception while exporting logs. 和 Invalid type <class 'NoneType'> of value None。

解决步骤

  1. 升级或应用包含 #42431 修复的 LiteLLM 版本(该修复已合并,提交 238f434153)。
  2. 若需自行打补丁,修改 litellm/integrations/otel/plumbing/events.py 中 record_operation_exception 构造的 Event,补上 body=message,使异常消息成为事件 body。
  3. 该改动依赖已有变量 message(异常消息已存在于 exception.message),不引入新的敏感信息,并且不依赖把 opentelemetry-* 从 1.28.0 升到 1.43.0。
  4. 修复后重启 LiteLLM 服务,再触发一次会抛出异常的请求,让 gen_ai.client.operation.exception 事件重新产生。

验证方法

在 OTLP collector 侧确认 gen_ai.client.operation.exception 事件已能收到,且日志中不再出现 Exception while exporting logs. 与 Invalid type <class 'NoneType'> of value None。

若在本地验证,Issue 作者补充的测试方式更可靠:运行真实的 encode_logs(...).SerializeToString() 编码路径,而非仅用 InMemoryLogExporter。按 Issue 数据,未修复时为 2 failed, 6 passed,修复后为 8 passed,完整 v2 otel 套件在锁定 opentelemetry-*==1.28.0 下为 342 passed, 6 skipped。

参考来源

BerriAI/litellm #36863

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 26005

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注