GitHub user Zhuoxi2000 created a discussion: [Discuss][Observability] 
OpenTelemetry GenAI export for Agent Traces (follow-up to #900)

## Motivation

#900 defines how Agent Traces are recorded in the Event Log, and deliberately 
lists OTel export as a non-goal of the recording scope. In that thread, 
@joeyutong agreed that OpenTelemetry export should be a supported follow-up 
once the recording contract settles, with the exact GenAI attribute mapping to 
be worked out as part of the exporter design. This discussion is that 
follow-up: a config-gated exporter that maps recorded Execution Events to the 
[OpenTelemetry GenAI semantic 
conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/), so any 
OTLP-compatible backend (Jaeger, Grafana Tempo, Langfuse, Phoenix, vendor APMs) 
can visualize and analyze agent runs without flink-agents shipping its own UI.

## Proposed mapping

Trace topology, aligned with the #900 recording model:

| flink-agents | OTel GenAI |
|---|---|
| Input run (`input_run_id`) | Trace (one run = one trace) |
| Execution (`execution_id` / `parent_execution_id`) | Span / parent Span |
| Agent execution | span `invoke_agent {agent_name}`; `gen_ai.operation.name = 
invoke_agent`, `gen_ai.agent.name` |
| Tool execution | span `execute_tool {tool_name}`; `gen_ai.operation.name = 
execute_tool`, `gen_ai.tool.name` |
| Model call | span `chat {model}`; `gen_ai.operation.name = chat`, 
`gen_ai.request.model`, `gen_ai.provider.name` |
| `business_key` | `gen_ai.conversation.id` |
| Lifecycle events (started/finished) | span start/end timestamps |
| `status` / `problem_category` | span status + `error.type` |
| Token usage | `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` |

**ID derivation.** Framework IDs stay opaque, as preferred in #900; the 
exporter derives fixed-width OTel IDs deterministically, e.g. `trace_id = 
truncate(SHA-256(input_run_id), 128 bits)` and `span_id = 
truncate(SHA-256(execution_id), 64 bits)`. Deterministic derivation keeps 
re-exports idempotent.

## Design points to agree on

1. **Where the exporter runs.** Two candidate shapes:
   - **(a) In-process**: an Execution Event listener in the runtime feeds an 
async OTLP exporter (batching, bounded queue, drop-on-overflow so it can never 
backpressure the job).
   - **(b) Out-of-band**: a separate consumer reads the Event Log and exports — 
zero impact on the running job, works retroactively, but requires event-log 
trace recording (#924) to be enabled.

   I lean toward (b) first, since it derives everything from the recording 
contract and adds no runtime risk, keeping (a) as a later option. Opinions 
welcome.

2. **Config surface.** `event-log.trace.otel.enabled` (default `false`, 
mirroring the recording flag), OTLP endpoint/protocol/headers, `service.name`. 
Content capture (prompt/response bodies) stays off by default and is opted into 
separately — gen_ai content capture has privacy and volume implications.

3. **Semconv version.** The `gen_ai.*` conventions are still `development` 
stability; we should pin the exported `schema_url` and document the target 
version. I'm engaging in the OTel GenAI SIG, so we can track upstream changes 
as they stabilize.

4. **Scope for 0.4.** Phase 1 = Java, spans-only, out-of-band exporter + 
config; Phase 2 = usage-metrics enrichment; Phase 3 = Python parity. Is Phase 1 
realistic for the 0.4 feature freeze (Sept 15)?

## What I'd deliver

I've already implemented the inverse mapping (OTel GenAI → storage) in a side 
project, so the attribute table above is grounded in working code. If 
maintainers agree with the general shape, I'll break this into concrete issues 
and start with Phase 1.

GitHub link: https://github.com/apache/flink-agents/discussions/929

----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]

Reply via email to