aboutsummaryrefslogtreecommitdiff
path: root/internal/storage
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-20 06:32:58 -0800
committerFuwn <[email protected]>2026-01-20 06:32:58 -0800
commita5e4fa5f372c6b2fb6e6194094015e5744c410dc (patch)
tree27378a93fdc8d27cebf79ca2c0e11480af68a8b6 /internal/storage
parentfeat: Add custom_head option for injecting HTML into head (diff)
downloadkaze-a5e4fa5f372c6b2fb6e6194094015e5744c410dc.tar.xz
kaze-a5e4fa5f372c6b2fb6e6194094015e5744c410dc.zip
feat: Add uptime tooltip showing last failure time and reason
Diffstat (limited to 'internal/storage')
-rw-r--r--internal/storage/sqlite.go32
1 files changed, 32 insertions, 0 deletions
diff --git a/internal/storage/sqlite.go b/internal/storage/sqlite.go
index 48cf432..ce62e67 100644
--- a/internal/storage/sqlite.go
+++ b/internal/storage/sqlite.go
@@ -52,6 +52,8 @@ type MonitorStats struct {
SSLExpiry *time.Time
SSLDaysLeft int
TotalChecks int64
+ LastFailure *time.Time // Time of last failure
+ LastFailureError string // Error message from last failure
}
// TickData represents aggregated data for one tick in the history bar
@@ -375,6 +377,36 @@ func (s *Storage) GetAllMonitorStats(ctx context.Context) (map[string]*MonitorSt
}
}
+ // Get last failure for each monitor
+ rows, err = s.db.QueryContext(ctx, `
+ SELECT monitor_name, timestamp, error
+ FROM check_results
+ WHERE status != 'up' AND error != ''
+ AND (monitor_name, timestamp) IN (
+ SELECT monitor_name, MAX(timestamp)
+ FROM check_results
+ WHERE status != 'up' AND error != ''
+ GROUP BY monitor_name
+ )
+ `)
+ if err != nil {
+ return nil, fmt.Errorf("failed to query last failures: %w", err)
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ var name string
+ var timestamp time.Time
+ var errorMsg string
+ if err := rows.Scan(&name, &timestamp, &errorMsg); err != nil {
+ return nil, fmt.Errorf("failed to scan last failure: %w", err)
+ }
+ if ms, ok := stats[name]; ok {
+ ms.LastFailure = &timestamp
+ ms.LastFailureError = errorMsg
+ }
+ }
+
return stats, nil
}