refactor: health check logic

This commit is contained in:
yusing 2025-05-10 22:55:20 +08:00
parent a8ba42e360
commit 30c76cfc5f
4 changed files with 36 additions and 34 deletions

View file

@ -21,15 +21,16 @@ func NewFileServerHealthMonitor(config *health.HealthCheckConfig, path string) *
func (s *FileServerHealthMonitor) CheckHealth() (*health.HealthCheckResult, error) { func (s *FileServerHealthMonitor) CheckHealth() (*health.HealthCheckResult, error) {
start := time.Now() start := time.Now()
_, err := os.Stat(s.path) _, err := os.Stat(s.path)
detail := ""
if err != nil { if err != nil {
detail = err.Error() if os.IsNotExist(err) {
return &health.HealthCheckResult{
Detail: err.Error(),
}, nil
}
return nil, err
} }
return &health.HealthCheckResult{ return &health.HealthCheckResult{
Healthy: err == nil, Healthy: true,
Latency: time.Since(start), Latency: time.Since(start),
Detail: detail,
}, nil }, nil
} }

View file

@ -37,19 +37,18 @@ func NewHTTPHealthMonitor(url *url.URL, config *health.HealthCheckConfig) *HTTPH
return mon return mon
} }
func (mon *HTTPHealthMonitor) CheckHealth() (result *health.HealthCheckResult, err error) { func (mon *HTTPHealthMonitor) CheckHealth() (*health.HealthCheckResult, error) {
ctx, cancel := mon.ContextWithTimeout("ping request timed out") ctx, cancel := mon.ContextWithTimeout("ping request timed out")
defer cancel() defer cancel()
req, reqErr := http.NewRequestWithContext( req, err := http.NewRequestWithContext(
ctx, ctx,
mon.method, mon.method,
mon.url.Load().JoinPath(mon.config.Path).String(), mon.url.Load().JoinPath(mon.config.Path).String(),
nil, nil,
) )
if reqErr != nil { if err != nil {
err = reqErr return nil, err
return
} }
req.Close = true req.Close = true
req.Header.Set("Connection", "close") req.Header.Set("Connection", "close")
@ -62,22 +61,26 @@ func (mon *HTTPHealthMonitor) CheckHealth() (result *health.HealthCheckResult, e
} }
lat := time.Since(start) lat := time.Since(start)
result = &health.HealthCheckResult{}
switch { switch {
case respErr != nil: case respErr != nil:
// treat tls error as healthy // treat tls error as healthy
var tlsErr *tls.CertificateVerificationError var tlsErr *tls.CertificateVerificationError
if ok := errors.As(respErr, &tlsErr); !ok { if ok := errors.As(respErr, &tlsErr); !ok {
result.Detail = respErr.Error() return &health.HealthCheckResult{
return Latency: lat,
Detail: respErr.Error(),
}, nil
} }
case resp.StatusCode == http.StatusServiceUnavailable: case resp.StatusCode == http.StatusServiceUnavailable:
result.Detail = resp.Status return &health.HealthCheckResult{
return Latency: lat,
Detail: resp.Status,
}, nil
} }
result.Latency = lat return &health.HealthCheckResult{
result.Healthy = true Latency: lat,
return Healthy: true,
}, nil
} }

View file

@ -215,15 +215,14 @@ func (mon *monitor) checkUpdateHealth() error {
result, err := mon.checkHealth() result, err := mon.checkHealth()
var lastStatus health.Status var lastStatus health.Status
if err != nil { switch {
if result == nil { case err != nil:
result = &health.HealthCheckResult{Healthy: false, Detail: err.Error()} result = &health.HealthCheckResult{Healthy: false, Detail: err.Error()}
}
lastStatus = mon.status.Swap(health.StatusError) lastStatus = mon.status.Swap(health.StatusError)
} else if result.Healthy { case result.Healthy:
lastStatus = mon.status.Swap(health.StatusHealthy) lastStatus = mon.status.Swap(health.StatusHealthy)
UpdateLastSeen(mon.service) UpdateLastSeen(mon.service)
} else { default:
lastStatus = mon.status.Swap(health.StatusUnhealthy) lastStatus = mon.status.Swap(health.StatusUnhealthy)
} }
mon.lastResult.Store(result) mon.lastResult.Store(result)

View file

@ -25,20 +25,19 @@ func NewRawHealthMonitor(url *url.URL, config *health.HealthCheckConfig) *RawHea
return mon return mon
} }
func (mon *RawHealthMonitor) CheckHealth() (result *health.HealthCheckResult, err error) { func (mon *RawHealthMonitor) CheckHealth() (*health.HealthCheckResult, error) {
ctx, cancel := mon.ContextWithTimeout("ping request timed out") ctx, cancel := mon.ContextWithTimeout("ping request timed out")
defer cancel() defer cancel()
url := mon.url.Load() url := mon.url.Load()
start := time.Now() start := time.Now()
conn, dialErr := mon.dialer.DialContext(ctx, url.Scheme, url.Host) conn, err := mon.dialer.DialContext(ctx, url.Scheme, url.Host)
result = new(health.HealthCheckResult) if err != nil {
if dialErr != nil { return nil, err
result.Detail = dialErr.Error()
return
} }
defer conn.Close() defer conn.Close()
result.Latency = time.Since(start) return &health.HealthCheckResult{
result.Healthy = true Latency: time.Since(start),
return Healthy: true,
}, nil
} }