Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46da71dd2c | ||
|
|
5b16fd3310 | ||
|
|
8746591889 | ||
|
|
bbceab0b24 |
No files matched your search
@@ -15,27 +15,3 @@ from `main` onto `prod`; `prod` never follows `main` automatically.
|
|||||||
|
|
||||||
Other issue branches do not touch this file; it changes only in its own PR to
|
Other issue branches do not touch this file; it changes only in its own PR to
|
||||||
`next`, because every branch editing `TODO.md` conflicts with every other.
|
`next`, because every branch editing `TODO.md` conflicts with every other.
|
||||||
|
|
||||||
# Status
|
|
||||||
|
|
||||||
On `next`:
|
|
||||||
|
|
||||||
- Repo standards (https://git.eeqj.de/sneak/rtnetmon/issues/1): the `script/`
|
|
||||||
entrypoints, the vendored `.golangci.yml`, and `REPO_POLICIES.md`.
|
|
||||||
- Interface detection on Linux and macOS
|
|
||||||
(https://git.eeqj.de/sneak/rtnetmon/issues/2).
|
|
||||||
- The fix for macOS VPN detection (https://git.eeqj.de/sneak/rtnetmon/issues/8).
|
|
||||||
- Starlink status lines (https://git.eeqj.de/sneak/rtnetmon/issues/3).
|
|
||||||
- A version stamp: built with `make build` or a plain `docker build .`, the
|
|
||||||
binary logs its git tag or short commit at startup
|
|
||||||
(https://git.eeqj.de/sneak/rtnetmon/issues/10).
|
|
||||||
- CI that runs `script/cibuild` on every push to a branch
|
|
||||||
(https://git.eeqj.de/sneak/rtnetmon/issues/12).
|
|
||||||
|
|
||||||
# Next Step
|
|
||||||
|
|
||||||
- `sneak` merges the milestone PR, https://git.eeqj.de/sneak/rtnetmon/pulls/6,
|
|
||||||
carrying `next` into `main`.
|
|
||||||
- A first run on a real Mac of what is on `next` now. The fix for
|
|
||||||
https://git.eeqj.de/sneak/rtnetmon/issues/8 has not run on a Mac yet;
|
|
||||||
`sneak`'s first run on his Mac is its test.
|
|
||||||
@@ -2,6 +2,7 @@ package monitor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/rtnetmon/internal/starlink"
|
"git.eeqj.de/sneak/rtnetmon/internal/starlink"
|
||||||
)
|
)
|
||||||
@@ -59,6 +60,9 @@ func (m *Monitor) TCPHosts() []string { return m.tcpHosts }
|
|||||||
// Interfaces returns the monitored interfaces.
|
// Interfaces returns the monitored interfaces.
|
||||||
func (m *Monitor) Interfaces() []*InterfaceStatus { return m.interfaces }
|
func (m *Monitor) Interfaces() []*InterfaceStatus { return m.interfaces }
|
||||||
|
|
||||||
|
// ClockStrings exposes clockStrings for external tests.
|
||||||
|
func ClockStrings(now time.Time) (string, string) { return clockStrings(now) }
|
||||||
|
|
||||||
// PingArgs exposes pingArgs for external tests.
|
// PingArgs exposes pingArgs for external tests.
|
||||||
func PingArgs(goos, iface, host string) []string { return pingArgs(goos, iface, host) }
|
func PingArgs(goos, iface, host string) []string { return pingArgs(goos, iface, host) }
|
||||||
|
|
||||||
|
|||||||
+11
-10
@@ -337,6 +337,15 @@ func drawICMPStats(scr tcell.Screen, y int, st *InterfaceStatus) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// uiLoop runs the UI event loop.
|
// uiLoop runs the UI event loop.
|
||||||
|
// clockFormat is the layout of both header clocks.
|
||||||
|
const clockFormat = time.RFC1123Z
|
||||||
|
|
||||||
|
// clockStrings renders the header clocks: UTC first, then the host's local
|
||||||
|
// time in whatever location now carries.
|
||||||
|
func clockStrings(now time.Time) (string, string) {
|
||||||
|
return now.UTC().Format(clockFormat), now.Format(clockFormat)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Monitor) uiLoop(ctx context.Context) {
|
func (m *Monitor) uiLoop(ctx context.Context) {
|
||||||
m.logf("UI loop started")
|
m.logf("UI loop started")
|
||||||
|
|
||||||
@@ -348,13 +357,6 @@ func (m *Monitor) uiLoop(ctx context.Context) {
|
|||||||
m.logf("Screen finalized")
|
m.logf("Screen finalized")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pstLoc, err := time.LoadLocation("America/Los_Angeles")
|
|
||||||
if err != nil {
|
|
||||||
m.logf("Error loading PST location: %v", err)
|
|
||||||
|
|
||||||
pstLoc = time.UTC
|
|
||||||
}
|
|
||||||
|
|
||||||
timestampSpinFrame := 0
|
timestampSpinFrame := 0
|
||||||
lastTimestampSpinUpdate := time.Now()
|
lastTimestampSpinUpdate := time.Now()
|
||||||
|
|
||||||
@@ -365,8 +367,7 @@ func (m *Monitor) uiLoop(ctx context.Context) {
|
|||||||
Put(m.screen, colLeft, rowTopRule, HLine(w), tcell.StyleDefault)
|
Put(m.screen, colLeft, rowTopRule, HLine(w), tcell.StyleDefault)
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
timeStr := now.Format(time.RFC1123Z)
|
timeStr, localTimeStr := clockStrings(now)
|
||||||
pstTimeStr := now.In(pstLoc).Format(time.RFC1123Z)
|
|
||||||
|
|
||||||
if time.Since(lastTimestampSpinUpdate) >= time.Second {
|
if time.Since(lastTimestampSpinUpdate) >= time.Second {
|
||||||
timestampSpinFrame = (timestampSpinFrame + 1) % len(brailleSpins())
|
timestampSpinFrame = (timestampSpinFrame + 1) % len(brailleSpins())
|
||||||
@@ -380,7 +381,7 @@ func (m *Monitor) uiLoop(ctx context.Context) {
|
|||||||
Put(m.screen, colSpinner, rowClock, string(brailleChar)+" ", tcell.StyleDefault)
|
Put(m.screen, colSpinner, rowClock, string(brailleChar)+" ", tcell.StyleDefault)
|
||||||
DrawRainbowText(m.screen, colMeter, rowClock, timeStr, colors)
|
DrawRainbowText(m.screen, colMeter, rowClock, timeStr, colors)
|
||||||
DrawRainbowText(m.screen, colMeter+len(timeStr)+clockGap, rowClock,
|
DrawRainbowText(m.screen, colMeter+len(timeStr)+clockGap, rowClock,
|
||||||
pstTimeStr, colors)
|
localTimeStr, colors)
|
||||||
Put(m.screen, colLeft, rowBottomRule, HLine(w), tcell.StyleDefault)
|
Put(m.screen, colLeft, rowBottomRule, HLine(w), tcell.StyleDefault)
|
||||||
|
|
||||||
runtime := time.Since(m.startTime).Round(time.Second).String()
|
runtime := time.Since(m.startTime).Round(time.Second).String()
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package monitor_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/rtnetmon/internal/monitor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestClockStrings checks that the header shows UTC first and the host's
|
||||||
|
// local time second, so the two differ whenever the host is not on UTC.
|
||||||
|
func TestClockStrings(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
berlin := time.FixedZone("CET", 3600)
|
||||||
|
now := time.Date(2026, time.November, 6, 20, 30, 0, 0, berlin)
|
||||||
|
|
||||||
|
utc, local := monitor.ClockStrings(now)
|
||||||
|
|
||||||
|
if want := "Fri, 06 Nov 2026 19:30:00 +0000"; utc != want {
|
||||||
|
t.Errorf("utc = %q, want %q", utc, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if want := "Fri, 06 Nov 2026 20:30:00 +0100"; local != want {
|
||||||
|
t.Errorf("local = %q, want %q", local, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user