summaryrefslogtreecommitdiff
path: root/internal/tui/dashboard/overview.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-24 09:45:02 +0200
committerPaul Buetow <paul@buetow.org>2026-02-24 09:45:02 +0200
commitf2d79f6459bbe1aa9bae2946e9773141cb184463 (patch)
treee683b901d2432ac7e28cd6e80f468da38edc280b /internal/tui/dashboard/overview.go
parent7fc16d6c98feae7aaee58666dc552384ceb4895e (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.go94
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"