From c55c6c84bce584f48a2dadc9a4afcb62eeccb03b Mon Sep 17 00:00:00 2001 From: yusing Date: Mon, 5 May 2025 13:27:00 +0800 Subject: [PATCH] feat(health): add health check detail to health api --- internal/idlewatcher/health.go | 15 +++++++++++++++ internal/net/gphttp/loadbalancer/loadbalancer.go | 6 ++++++ internal/route/routes/query.go | 2 ++ internal/watcher/health/monitor/monitor.go | 9 +++++++++ internal/watcher/health/types.go | 1 + 5 files changed, 33 insertions(+) diff --git a/internal/idlewatcher/health.go b/internal/idlewatcher/health.go index 5a256a4..8e3a8c6 100644 --- a/internal/idlewatcher/health.go +++ b/internal/idlewatcher/health.go @@ -65,6 +65,21 @@ func (w *Watcher) Status() health.Status { return health.StatusNapping } +// Detail implements health.HealthMonitor. +func (w *Watcher) Detail() string { + state := w.state.Load() + if state.err != nil { + return state.err.Error() + } + if !state.ready { + return "not ready" + } + if state.status == idlewatcher.ContainerStatusRunning { + return "starting" + } + return "napping" +} + func checkUpdateState(key string) (w *Watcher, ready bool, err error) { watcherMapMu.RLock() w, ok := watcherMap[key] diff --git a/internal/net/gphttp/loadbalancer/loadbalancer.go b/internal/net/gphttp/loadbalancer/loadbalancer.go index 972bbec..d36bf98 100644 --- a/internal/net/gphttp/loadbalancer/loadbalancer.go +++ b/internal/net/gphttp/loadbalancer/loadbalancer.go @@ -266,6 +266,12 @@ func (lb *LoadBalancer) Status() health.Status { return status } +// Detail implements health.HealthMonitor. +func (lb *LoadBalancer) Detail() string { + _, numHealthy := lb.status() + return fmt.Sprintf("%d/%d servers are healthy", numHealthy, lb.pool.Size()) +} + func (lb *LoadBalancer) status() (status health.Status, numHealthy int) { if lb.pool.Size() == 0 { return health.StatusUnknown, 0 diff --git a/internal/route/routes/query.go b/internal/route/routes/query.go index 3ba7088..44a0264 100644 --- a/internal/route/routes/query.go +++ b/internal/route/routes/query.go @@ -16,12 +16,14 @@ func getHealthInfo(r Route) map[string]string { "status": "unknown", "uptime": "n/a", "latency": "n/a", + "detail": "n/a", } } return map[string]string{ "status": mon.Status().String(), "uptime": mon.Uptime().Round(time.Second).String(), "latency": mon.Latency().Round(time.Microsecond).String(), + "detail": mon.Detail(), } } diff --git a/internal/watcher/health/monitor/monitor.go b/internal/watcher/health/monitor/monitor.go index 8f4ddf3..20bc8ed 100644 --- a/internal/watcher/health/monitor/monitor.go +++ b/internal/watcher/health/monitor/monitor.go @@ -168,6 +168,15 @@ func (mon *monitor) Latency() time.Duration { return res.Latency } +// Detail implements HealthMonitor. +func (mon *monitor) Detail() string { + res := mon.lastResult.Load() + if res == nil { + return "" + } + return res.Detail +} + // Name implements HealthMonitor. func (mon *monitor) Name() string { parts := strutils.SplitRune(mon.service, '/') diff --git a/internal/watcher/health/types.go b/internal/watcher/health/types.go index 0f6610e..0d245cd 100644 --- a/internal/watcher/health/types.go +++ b/internal/watcher/health/types.go @@ -19,6 +19,7 @@ type ( Status() Status Uptime() time.Duration Latency() time.Duration + Detail() string } HealthMonitor interface { task.TaskStarter