Skip to content

Observability

Run Trace

Flame graph of an agent run with click-to-zoom spans, plus a breakdown of where time, tokens and cost went.

2 variantsMIT

Preview

0ms1ms1ms

Click a block to zoom in, Esc to step back out

RecordingRecording 0ms1 spans

Installation

Copies the component into components/ui and installs its dependencies and theme tokens.

pnpm dlx shadcn@latest add https://tuffui.com/r/run-trace.json

Usage

Pass your own data and wire the callbacks to your agent runtime.

import { RunTrace, type TraceSpan } from "@/components/ui/run-trace";

// Map your tracer's spans (OpenTelemetry, Langfuse, agent SDK events) to TraceSpan.
export function Trace({ spans, elapsedMs }: { spans: TraceSpan[]; elapsedMs: number }) {
  return (
    <RunTrace
      data={{ spans, elapsedMs }}
      onZoom={(span) => analytics.track("trace_zoom", { span: span?.name })}
    />
  );
}

// While the run is live, leave endMs undefined on open spans and
// re-render with a growing elapsedMs (e.g. from requestAnimationFrame).

Props

PropTypeDefaultDescription
data*{ spans: TraceSpan[]; elapsedMs: number }—Spans of one run with offsets from its start. elapsedMs drives running spans and the time axis.
view"flame" | "breakdown""flame"Flame is a zoomable flame graph: click a span to fill the width with it, Esc or the breadcrumb to zoom out. Breakdown totals time, tokens or cost per tool and model.
onZoom(span: TraceSpan | null) => void—Called when the flame graph zooms into a span, or back to the whole run.
classNamestring—Extra classes for the root section.
type TraceSpan = {
  id: string;
  parentId?: string;       // nests the span under another one
  name: string;
  kind: "llm" | "tool" | "agent" | "retrieval";
  startMs: number;         // offset from the start of the run
  endMs?: number;          // undefined while running
  model?: string;
  tokens?: { input: number; output: number };
  costUsd?: number;
  status?: "ok" | "error";
};