diff --git a/main.go b/main.go index 5ee492a..1dc89b5 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,7 @@ import ( //go:embed static var embeddedStaticFiles embed.FS -const version = "1.0.2" +const version = "1.0.3" // --------------------------------------------------------------------------- // Config structs @@ -467,6 +467,8 @@ type APIState struct { ImbalancePercent float32 `json:"imbalance_percent"` BiasPercent float32 `json:"bias_percent"` LastUpdate string `json:"last_update"` + ServerTime string `json:"server_time"` + Stale bool `json:"stale"` DroppedSamples uint64 `json:"dropped_samples"` DroppedEvents uint64 `json:"dropped_events"` } @@ -927,6 +929,18 @@ func getConfigSnapshot() Config { return cfg } +func staleThreshold() time.Duration { + pollMs := getConfigSnapshot().PLC.PollMs + if pollMs <= 0 { + pollMs = 500 + } + staleMs := pollMs * 4 + if staleMs < 2500 { + staleMs = 2500 + } + return time.Duration(staleMs) * time.Millisecond +} + func hotReloadSectionsLocked(dst *Config, src Config) { dst.Thresholds = src.Thresholds dst.Trend = src.Trend @@ -1092,10 +1106,17 @@ func snapshotState() APIState { state.RLock() defer state.RUnlock() + now := time.Now() lastUpdate := "" if !state.LastUpdate.IsZero() { lastUpdate = state.LastUpdate.Format(time.RFC3339Nano) } + + stale := false + if state.Connected && !state.LastUpdate.IsZero() { + stale = now.Sub(state.LastUpdate) > staleThreshold() + } + return APIState{ Connected: state.Connected, SilaL: state.SilaL, @@ -1107,6 +1128,8 @@ func snapshotState() APIState { ImbalancePercent: state.ImbalancePercent, BiasPercent: state.BiasPercent, LastUpdate: lastUpdate, + ServerTime: now.Format(time.RFC3339Nano), + Stale: stale, DroppedSamples: state.DroppedSamples, DroppedEvents: state.DroppedEvents, } @@ -2753,7 +2776,8 @@ func main() { IdleTimeout: 60 * time.Second, } - log.Printf("Listening on http://localhost%s", cfg.Server.ListenAddr) + log.Printf("Listening address: %s", cfg.Server.ListenAddr) + log.Printf("Open locally: http://localhost%s", cfg.Server.ListenAddr) log.Printf("License API: GET /api/license/status | GET /api/license/request | POST /api/license/activate") go func() {