diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-24 09:45:02 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-24 09:45:02 +0200 |
| commit | f2d79f6459bbe1aa9bae2946e9773141cb184463 (patch) | |
| tree | e683b901d2432ac7e28cd6e80f468da38edc280b /internal/tui/dashboard/overview.go | |
| parent | 7fc16d6c98feae7aaee58666dc552384ceb4895e (diff) | |
tui: wire full dashboard tabs and improve overview summaries
Diffstat (limited to 'internal/tui/dashboard/overview.go')
| -rw-r--r-- | internal/tui/dashboard/overview.go | 94 |
1 files changed, 85 insertions, 9 deletions
diff --git a/internal/tui/dashboard/overview.go b/internal/tui/dashboard/overview.go index 3f563d4..8b6b13c 100644 --- a/internal/tui/dashboard/overview.go +++ b/internal/tui/dashboard/overview.go @@ -3,7 +3,7 @@ package dashboard import ( "fmt" "ior/internal/statsengine" - "ior/internal/tui" + common "ior/internal/tui/common" "strings" "time" ) @@ -11,7 +11,7 @@ import ( func renderOverview(snap *statsengine.Snapshot, width, height int) string { _ = height if snap == nil { - return tui.PanelStyle.Render("Overview: waiting for stats...") + return common.PanelStyle.Render("Overview: waiting for stats...") } boxWidth := summaryBoxWidth(width) @@ -30,14 +30,22 @@ func renderOverview(snap *statsengine.Snapshot, width, height int) string { latencySpark := "Latency: " + renderSparkline(snap.LatencySeriesNs(), sparklineWidth(width)) throughputSpark := "Throughput: " + renderSparkline(snap.ThroughputSeriesB(), sparklineWidth(width)) topSyscalls := "Top syscalls: " + summarizeTopSyscalls(snap) + topFiles := "Top files: " + summarizeTopFiles(snap) + topProcesses := "Top processes: " + summarizeTopProcesses(snap) + latencyHist := "Latency buckets: " + summarizeHistogramBrief(snap.LatencyHistogram) + gapHist := "Gap buckets: " + summarizeHistogramBrief(snap.GapHistogram) return strings.Join( []string{ row, - tui.HighlightStyle.Render(trends), - tui.PanelStyle.Render(latencySpark), - tui.PanelStyle.Render(throughputSpark), - tui.PanelStyle.Render(topSyscalls), + common.HighlightStyle.Render(trends), + common.PanelStyle.Render(latencySpark), + common.PanelStyle.Render(throughputSpark), + common.PanelStyle.Render(topSyscalls), + common.PanelStyle.Render(topFiles), + common.PanelStyle.Render(topProcesses), + common.PanelStyle.Render(latencyHist), + common.PanelStyle.Render(gapHist), }, "\n", ) @@ -50,7 +58,7 @@ func renderSyscallBox(snap *statsengine.Snapshot, width int) string { snap.TotalSyscalls, snap.SyscallRatePerSec, ) - return tui.PanelStyle.Width(width).Render(content) + return common.PanelStyle.Width(width).Render(content) } func renderBytesBox(snap *statsengine.Snapshot, width int) string { @@ -60,7 +68,7 @@ func renderBytesBox(snap *statsengine.Snapshot, width int) string { formatBytes(snap.WriteBytesPerSec), formatBytes(float64(snap.TotalBytes)), ) - return tui.PanelStyle.Width(width).Render(content) + return common.PanelStyle.Width(width).Render(content) } func renderErrorBox(snap *statsengine.Snapshot, width int) string { @@ -74,7 +82,7 @@ func renderErrorBox(snap *statsengine.Snapshot, width int) string { errPercent, snap.LatencyMeanNs, ) - return tui.PanelStyle.Width(width).Render(content) + return common.PanelStyle.Width(width).Render(content) } func trendWithArrow(trend statsengine.Trend) string { @@ -106,6 +114,74 @@ func summarizeTopSyscalls(snap *statsengine.Snapshot) string { return strings.Join(parts, ", ") } +func summarizeTopFiles(snap *statsengine.Snapshot) string { + files := snap.Files() + if len(files) == 0 { + return "none" + } + + limit := 3 + if len(files) < limit { + limit = len(files) + } + + parts := make([]string, 0, limit) + for _, f := range files[:limit] { + parts = append(parts, fmt.Sprintf("%s(%d)", trimPathTail(f.Path, 24), f.Accesses)) + } + return strings.Join(parts, ", ") +} + +func summarizeTopProcesses(snap *statsengine.Snapshot) string { + processes := snap.Processes() + if len(processes) == 0 { + return "none" + } + + limit := 3 + if len(processes) < limit { + limit = len(processes) + } + + parts := make([]string, 0, limit) + for _, p := range processes[:limit] { + parts = append(parts, fmt.Sprintf("%s/%d(%d)", p.Comm, p.PID, p.Syscalls)) + } + return strings.Join(parts, ", ") +} + +func summarizeHistogramBrief(hist statsengine.HistogramSnapshot) string { + buckets := hist.Buckets() + if len(buckets) == 0 || hist.Total == 0 { + return "none" + } + + parts := make([]string, 0, 3) + for _, b := range buckets { + if b.Count == 0 { + continue + } + parts = append(parts, fmt.Sprintf("%s:%d", b.Label, b.Count)) + if len(parts) == 3 { + break + } + } + if len(parts) == 0 { + return "none" + } + return strings.Join(parts, ", ") +} + +func trimPathTail(path string, max int) string { + if len(path) <= max { + return path + } + if max <= 3 { + return path[len(path)-max:] + } + return "..." + path[len(path)-max+3:] +} + func formatElapsed(elapsed time.Duration) string { if elapsed <= 0 { return "0s" |
