From e93df20aee91f15e7df43144f3c1a8ca7808059d Mon Sep 17 00:00:00 2001 From: Soumalya Das Date: Wed, 8 Jul 2026 16:27:11 +0530 Subject: [PATCH] enrich json, show refresh interval and bits indicator, extend sampling to 5min --- CHANGELOG.md | 9 +++++++++ VERSION | 2 +- cmd/flow/main.go | 18 ++++++++++++------ internal/ui/model.go | 6 ++++++ internal/ui/views.go | 13 +++++++++++++ 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0548264..b339a5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## [0.1.5] - 2026-07-08 + +### Added + +- Enriched JSON snapshot output -- `--once --json` now includes `status`, `timestamp` (RFC3339), `download_human`, and `upload_human` fields for self-contained script consumption. +- Refresh interval permanently displayed in footer when non-default (e.g. "every 5s"). +- Extended sampling range up to 5 minutes (30s, 60s, 300s) for long-term overnight monitoring. +- Bits indicator -- footer shows `[bits]` label when bits mode is active for clear differentiation from bytes mode. + ## [0.1.4] - 2026-07-07 ### Fixed diff --git a/VERSION b/VERSION index 446ba66..def9a01 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.4 \ No newline at end of file +0.1.5 \ No newline at end of file diff --git a/cmd/flow/main.go b/cmd/flow/main.go index 134da84..aa103ce 100644 --- a/cmd/flow/main.go +++ b/cmd/flow/main.go @@ -177,13 +177,19 @@ func runOnce(col *collector.Collector, smp *sampler.Sampler, refresh time.Durati cancel() if asJSON { + down := ui.FormatBpsExt(s.DownBps, ui.UnitAuto, bits) + up := ui.FormatBpsExt(s.UpBps, ui.UnitAuto, bits) out := map[string]interface{}{ - "download_bps": s.DownBps, - "upload_bps": s.UpBps, - "peak_down_bps": s.DownBps, // peak = current in one-shot mode - "peak_up_bps": s.UpBps, - "interface": s.Interface, - "unit_display": autoUnitExt(s.DownBps, bits), + "status": "ok", + "timestamp": time.Now().Format(time.RFC3339), + "interface": s.Interface, + "download_bps": s.DownBps, + "upload_bps": s.UpBps, + "download_human": down, + "upload_human": up, + "peak_down_bps": s.DownBps, + "peak_up_bps": s.UpBps, + "unit_display": autoUnitExt(s.DownBps, bits), } enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") diff --git a/internal/ui/model.go b/internal/ui/model.go index b4184eb..d8686d9 100644 --- a/internal/ui/model.go +++ b/internal/ui/model.go @@ -347,6 +347,12 @@ func (m *Model) adjustRefreshInterval(faster bool) { 500 * time.Millisecond, 1 * time.Second, 2 * time.Second, + 3 * time.Second, + 5 * time.Second, + 10 * time.Second, + 30 * time.Second, + 60 * time.Second, + 300 * time.Second, } idx := -1 diff --git a/internal/ui/views.go b/internal/ui/views.go index d2ccd2e..1edf9e9 100644 --- a/internal/ui/views.go +++ b/internal/ui/views.go @@ -446,6 +446,12 @@ func dashboardContentLines(m Model, mode ViewMode) []string { if m.paused { ifaceStr += theme.Muted().Render(" paused") } + if m.bitsMode { + ifaceStr += theme.Muted().Render(" [bits]") + } + if m.refreshInterval != 100*time.Millisecond { + ifaceStr += theme.Muted().Render(" " + formatInterval(m.refreshInterval)) + } renderKey := func(k, desc string) string { return lipgloss.NewStyle().Foreground(lipgloss.Color(theme.GetAccentColor())).Bold(true).Render(k) + " " + theme.Muted().Render(desc) @@ -701,6 +707,13 @@ func max(a, b int) int { return b } +func formatInterval(d time.Duration) string { + if d >= time.Second { + return fmt.Sprintf("every %ds", int(d.Seconds())) + } + return fmt.Sprintf("every %dms", d.Milliseconds()) +} + func min(a, b int) int { if a < b { return a