Trace Chart
Distributed-trace waterfall of nested spans on a shared time axis.
Overview
The TraceChart renders a waterfall of TraceSpan
rows, modeled on the spans of a distributed trace. Each span is drawn as one row with an
indented name and a duration bar positioned on a shared time axis — offset by
StartMs and sized by DurationMs. Nested spans supplied via child
<TraceSpan> elements are flattened and indented by depth. Bar edges use
eighth-blocks for sub-cell precision. Provide spans inline or bind SpansSource.
Properties
| Property | Type | Description |
|---|---|---|
Spans | IList<TraceSpan> | Inline span collection (content property). |
SpansSource | IEnumerable | Bound span collection; overrides Spans. |
LabelWidth | int | Width (cells) of the left gutter holding span names. |
RowSpacing | int | Blank rows inserted between consecutive spans (default 1). |
SelectedIndex | int | Index of the selected row in the flattened span list (-1 = none). Two-way bindable. |
SelectedSpan | object | The selected span, kept in sync with SelectedIndex. Two-way bindable. |
SelectedBackground / SelectedForeground | Color | Colors of the highlighted selected row. |
TraceSpan fields: Name, StartMs,
DurationMs, Depth, Color, and nested
Children.
Data Binding
Bind a collection of spans from a ViewModel to SpansSource. The chart
subscribes to INotifyCollectionChanged, so streaming spans in as a trace
completes re-renders the waterfall automatically. Data classes and ViewModels must be
public or internal so the AOT source generator can bind them.
public sealed class TraceViewModel : ViewModelBase
{
public ObservableCollection<TraceSpan> Spans { get; } =
[
new TraceSpan { Name = "http.request", StartMs = 0, DurationMs = 120 },
new TraceSpan { Name = "auth", StartMs = 2, DurationMs = 15, Depth = 1 },
];
// Spans arriving from a live trace re-render the waterfall automatically.
public void OnSpanReceived(string name, double start, double duration, int depth) =>
Spans.Add(new TraceSpan { Name = name, StartMs = start, DurationMs = duration, Depth = depth });
}
<TraceChart SpansSource="{Binding Spans}" LabelWidth="18" />
A bound span list is flattened as-is; set each span's Depth to control
indentation, or supply a nested tree via Children and let the chart derive it.
Interactivity
The waterfall is focusable and selectable. Give it focus (Tab, or click it) and use
↑/↓ — plus Home/End — to move the row selection, or click a
row directly. The selected row is highlighted (brighter while the chart holds focus) and both
SelectedIndex and SelectedSpan update two-way, so you can bind them
to a details pane:
<TraceChart SpansSource="{Binding Spans}"
SelectedSpan="{Binding Selected, Mode=TwoWay}" />
Key Concepts
- All spans share one time axis; a bar's position encodes
StartMs. - Nested
Childrenare flattened; depth drives label indentation. - Bar right-edges use left-eighth blocks for sub-cell duration precision.
- Row colors come from the theme palette, overridable via
TraceSpan.Color. - Bind live traces through
SpansSource; drive/observe selection viaSelectedIndex/SelectedSpan.