Skip to content

[Proposal] 提供原生 OpenTelemetry handler,按 GenAI 语义约定为 ChatModel / Tool / Retriever / Graph / ADK 上报 span #1028

Open

Description

@wucm667

Is your feature request related to a problem? Please describe.

要给 eino 应用接入可观测性,目前必须自行实现 callbacks.Handler。社区生态里有 Langfuse / cozeloop 两个实现(位于 eino-ext),但它们都是面向各自后端的专有映射,无法直接对接通用的 OTel collector / APM。eino-ext#328 提出 OTel 上报,但范围只限 Indexer / Retriever。

OpenTelemetry 已经发布 GenAI Semantic Conventions(gen_ai.system、gen_ai.request.model、gen_ai.usage.input_tokens、gen_ai.operation.name 等),主流框架普遍原生支持(Google ADK、Pydantic AI + Logfire、Mastra、LlamaIndex)。eino 缺一个框架自带、与后端解耦的 OTel handler。这本质上是「切面扩展」能力的标准化输出。

Describe the solution you'd like

新增 callbacks/otel 包,提供一个标准 handler:

package otel

func NewHandler(tp trace.TracerProvider, mp metric.MeterProvider, opts ...Option) callbacks.Handler

行为:

  1. 按 RunInfo.Component(model / tool / retriever / ...)映射到 gen_ai.operation.name(chat / execute_tool / embeddings / ...)。
  2. OnStart 注入 gen_ai.request.*,OnEnd 注入 gen_ai.response.* 与 gen_ai.usage.*。
  3. 流式场景在 OnEndWithStreamOutput 内累计 token,stream 关闭时一次性落 span。
  4. Graph / ADK 节点产生父 span,Component 调用作为子 span,形成完整调用树。
  5. Metrics:gen_ai.client.token.usage、gen_ai.client.operation.duration 直方图。

分期:

  • 一期:ChatModel / Tool / Embedding / Retriever / Indexer 的 span + 标准 attribute
  • 二期:Graph 节点与 ADK Agent 的父子 span 层级 + AgentEvent 拓扑
  • 三期:AgenticMessage(Responses API)的 reasoning / tool 双 span 表示

Describe alternatives you've considered

  • 继续用 Langfuse / cozeloop handler:绑定特定后端,无法对接已有的 OTel collector / Jaeger / Tempo / 各类 APM。
  • 由用户各自实现 OTel handler:每个团队重复造轮子,且很难统一遵循 GenAI semconv,trace 不可跨项目复用。
  • 只做 metrics 不做 trace:丢失调用树,无法定位多 Agent / 多节点链路。

Additional context

  • OTel GenAI Semantic Conventions: https://opentelemetry.io/docs/specs/semconv/gen-ai/
  • 现有实现可参考:eino-ext callbacks/langfuse。
  • 关联:eino-ext#328(仅 indexer/retriever,范围窄)。
  • 放置位置(主仓库 callbacks/otel vs eino-ext)可讨论;倾向主仓库,因为 OTel 是行业标准、且不引入重后端依赖。

愿意在 maintainer 认可方向后承担实现。

Activity

  1. March-77 commented on Jul 24, 2026

    @March-77

    This needs a placement/dependency decision before implementation. My suggested first increment is an eino-ext callback handler (to avoid adding OTel SDK dependencies to core) covering ChatModel/Tool/Retriever/Indexer spans first, pinned to one GenAI semconv version, with in-memory exporter tests for parentage, attributes, errors, and streaming completion. Graph/ADK topology and metrics can follow after the base span contract stabilizes. Please confirm core vs eino-ext and the intended semconv stability level.

  2. SilenceShine commented on Aug 6, 2026

    @SilenceShine

    我也想要

  3. Ethanz11-creat commented on Aug 30, 2026

    @Ethanz11-creat

    Implemented this as a backend-agnostic handler in eino-ext: cloudwego/eino-ext#980.

    Placement rationale: I followed the suggestion to keep the OpenTelemetry SDK out of eino core (which currently has no observability dependencies) by putting the handler in eino-ext alongside langfuse and cozeloop. The handler is a standard callbacks.Handler, so it works anywhere core callbacks work, including ADK.

    What it covers today:

    • gen_ai.operation.name mapping: ChatModel/AgenticModel → chat, Embedding/Indexer → embeddings, Retriever → retrieve, Tool/tools nodes → execute_tool, Agent/Graph/Workflow/Chain → invoke_agent
    • gen_ai.system from the component implementation type (lowercased)
    • gen_ai.request.model from chat model / embedding callbacks
    • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens from chat model / embedding callbacks
    • Streaming invocations get a span whose lifetime follows the stream

    Not yet covered: metrics (token-usage counters / histograms) and gen_ai.client.* event attributes. I left those out to keep this first increment reviewable — happy to add them as a follow-up if maintainers want the full surface.

    Would love maintainer feedback on whether this placement and scope matches the project direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions