Problem
Collector.Snapshot() in internal/source/collector.go assembles DataMsg from three separate lock acquisitions:
c.store.Snapshot() — acquires/releases ss.mu.RLock
c.mu.Lock for alerts
c.store.DailyTotal() — acquires/releases ss.mu.RLock again
Between these calls, the background goroutine can run processAllTails(), updating session metrics. The returned DataMsg can have session costs from time T but daily total from time T+delta.
Impact
Cosmetic — the TUI may briefly show numbers that don't add up. Self-corrects on the next 1-second tick. No crash or data loss.
Suggested Fix
Add a SnapshotWithTotal() ([]SessionMetrics, float64) method to SessionStore that returns both under a single RLock.
Files
internal/source/collector.go:192-245
internal/metrics/session.go
Problem
Collector.Snapshot()ininternal/source/collector.goassemblesDataMsgfrom three separate lock acquisitions:c.store.Snapshot()— acquires/releasesss.mu.RLockc.mu.Lockfor alertsc.store.DailyTotal()— acquires/releasesss.mu.RLockagainBetween these calls, the background goroutine can run
processAllTails(), updating session metrics. The returnedDataMsgcan have session costs from time T but daily total from time T+delta.Impact
Cosmetic — the TUI may briefly show numbers that don't add up. Self-corrects on the next 1-second tick. No crash or data loss.
Suggested Fix
Add a
SnapshotWithTotal() ([]SessionMetrics, float64)method toSessionStorethat returns both under a single RLock.Files
internal/source/collector.go:192-245internal/metrics/session.go