|
|
|
@ -4,6 +4,7 @@ import ( |
|
|
|
|
"context" |
|
|
|
|
"encoding/json" |
|
|
|
|
"net/http" |
|
|
|
|
"sync" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type Status string |
|
|
|
@ -24,12 +25,14 @@ func (f CheckerFunc) Check(ctx context.Context) error { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Health struct { |
|
|
|
|
lock sync.RWMutex |
|
|
|
|
status Status |
|
|
|
|
checkers map[string]Checker |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func New() *Health { |
|
|
|
|
h := &Health{ |
|
|
|
|
lock: sync.RWMutex{}, |
|
|
|
|
status: Down, |
|
|
|
|
checkers: make(map[string]Checker), |
|
|
|
|
} |
|
|
|
@ -37,20 +40,28 @@ func New() *Health { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (h *Health) Register(name string, checker CheckerFunc) { |
|
|
|
|
h.lock.Lock() |
|
|
|
|
defer h.lock.Unlock() |
|
|
|
|
h.checkers[name] = checker |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (h *Health) Start(_ context.Context) error { |
|
|
|
|
h.lock.Lock() |
|
|
|
|
defer h.lock.Unlock() |
|
|
|
|
h.status = Up |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (h *Health) Stop(_ context.Context) error { |
|
|
|
|
h.lock.Lock() |
|
|
|
|
defer h.lock.Unlock() |
|
|
|
|
h.status = Down |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (h *Health) Check(ctx context.Context) Result { |
|
|
|
|
h.lock.RLock() |
|
|
|
|
defer h.lock.RUnlock() |
|
|
|
|
res := Result{Status: h.status, Details: make(map[string]Detail, len(h.checkers))} |
|
|
|
|
for n, c := range h.checkers { |
|
|
|
|
if err := c.Check(ctx); err != nil { |
|
|
|
@ -64,7 +75,9 @@ func (h *Health) Check(ctx context.Context) Result { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (h *Health) CheckService(ctx context.Context, svc string) Detail { |
|
|
|
|
h.lock.RLock() |
|
|
|
|
c, ok := h.checkers[svc] |
|
|
|
|
h.lock.RUnlock() |
|
|
|
|
if !ok { |
|
|
|
|
return Detail{Status: Down, Error: "service not find"} |
|
|
|
|
} |
|
|
|
|