Skip to content

ai(observability): the Trace name column is empty — no $ai_trace event is ever emitted #10221

Description

@JSONbored

Part of epic #8286 (Phase 3 — AI observability).

Problem

The Trace name column is empty for every row in PostHog's Traces view, because the project emits no $ai_trace event at all — only $ai_generation and $ai_embedding.

PostHog derives the trace row itself from the generations (which is why latency and cost populate), but the name comes from a trace-level event. This is confirmed upstream: PostHog/posthog#33179$ai_span_name set on a generation does not populate the Traces tab's Trace name column; it needs the trace event.

So every trace reads as an anonymous id, and there is no way to tell a gate review from an embedding batch from a summary at a glance.

What a trace envelope would carry

withReviewPipelineSpan (src/selfhost/review-tracing.ts) already wraps a whole review and is the natural chokepoint — it has the name, repo, PR number and the ambient OTel trace id that #10187 made the generations group by. A $ai_trace emitted as that span completes would carry $ai_trace_id, $ai_span_name, $ai_latency, and $ai_is_error/$ai_error.

The two things that make this non-trivial

  1. Duplicate emission. withReviewPipelineSpan is called from ~7 sites in src/queue/processors.ts, and they can nest. PostHog expects one $ai_trace per trace id, so the envelope must be emitted once — by the outermost span only — not once per nested call.
  2. Empty traces. Not every pipeline span wraps an AI call (the gate, for instance). Emitting unconditionally would create trace rows with zero generations, which is worse than an unnamed trace. The envelope should only be emitted when at least one generation was actually captured under that trace id.

Both point at the same shape: track, per trace id, whether any generation was captured, and emit the envelope on outermost-span exit only if so.

Deliverables

  • $ai_trace emitted once per trace, named from the pipeline span.
  • Never emitted for a trace with no generations under it.
  • Never emitted twice for a nested span.
  • Carries the same repo group and operational context as the generations, so the trace and its children agree.
  • $ai_session_id considered while here — it is the documented way to group related traces, and a review with retries is exactly that.

Related

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions