parent
0536c38150
commit
4d2fb959c5
@ -0,0 +1,73 @@ |
|||||||
|
package health |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"sync" |
||||||
|
"time" |
||||||
|
) |
||||||
|
|
||||||
|
type Checker interface { |
||||||
|
Check(ctx context.Context) (interface{}, error) |
||||||
|
} |
||||||
|
|
||||||
|
type Watcher func(string) |
||||||
|
|
||||||
|
type checker struct { |
||||||
|
Name string |
||||||
|
intervalTime time.Duration |
||||||
|
timeout time.Duration |
||||||
|
Checker |
||||||
|
CheckerStatus |
||||||
|
sync.RWMutex |
||||||
|
Watcher |
||||||
|
} |
||||||
|
|
||||||
|
func NewChecker(name string, checker Checker) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
func (c *checker) check(ctx context.Context) bool { |
||||||
|
defer func() { |
||||||
|
recover() |
||||||
|
}() |
||||||
|
ctx, cancel := context.WithTimeout(ctx, c.timeout) |
||||||
|
defer cancel() |
||||||
|
detail, err := c.Check(ctx) |
||||||
|
status := StatusUp |
||||||
|
if err != nil { |
||||||
|
status = StatusDown |
||||||
|
} |
||||||
|
c.Lock() |
||||||
|
defer c.Unlock() |
||||||
|
old := c.CheckerStatus |
||||||
|
c.CheckerStatus = CheckerStatus{ |
||||||
|
Status: status, |
||||||
|
Detail: detail, |
||||||
|
Err: err, |
||||||
|
} |
||||||
|
if c.CheckerStatus == old { |
||||||
|
return false |
||||||
|
} |
||||||
|
return true |
||||||
|
} |
||||||
|
|
||||||
|
func (c *checker) run(ctx context.Context) { |
||||||
|
for { |
||||||
|
select { |
||||||
|
case <-ctx.Done(): |
||||||
|
return |
||||||
|
default: |
||||||
|
} |
||||||
|
if c.check(ctx) { |
||||||
|
//发送改变通知
|
||||||
|
c.Watcher(c.Name) |
||||||
|
} |
||||||
|
time.Sleep(c.intervalTime) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *checker) getStatus() CheckerStatus { |
||||||
|
c.RLock() |
||||||
|
defer c.RUnlock() |
||||||
|
return c.CheckerStatus |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
package health |
||||||
|
|
||||||
|
import ( |
||||||
|
"golang.org/x/net/context" |
||||||
|
) |
||||||
|
|
||||||
|
type CheckerMgr struct { |
||||||
|
checkers map[string]checker |
||||||
|
ctx context.Context |
||||||
|
cancel func() |
||||||
|
watchers []chan string |
||||||
|
} |
||||||
|
|
||||||
|
func New(ctx context.Context) *CheckerMgr { |
||||||
|
c, cancel := context.WithCancel(ctx) |
||||||
|
return &CheckerMgr{ |
||||||
|
checkers: make(map[string]checker), |
||||||
|
ctx: c, |
||||||
|
cancel: cancel, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *CheckerMgr) Start() { |
||||||
|
for _, v := range c.checkers { |
||||||
|
go func() { |
||||||
|
v.run(c.ctx) |
||||||
|
}() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (c *CheckerMgr) Stop() { |
||||||
|
c.cancel() |
||||||
|
} |
||||||
|
|
||||||
|
type StatusResult struct { |
||||||
|
Name string |
||||||
|
CheckerStatus |
||||||
|
} |
||||||
|
|
||||||
|
// GetStatus
|
||||||
|
//
|
||||||
|
// if name is nil return all status
|
||||||
|
func (c *CheckerMgr) GetStatus(name ...string) []StatusResult { |
||||||
|
status := make([]StatusResult, 0, len(name)) |
||||||
|
if len(name) == 0 { |
||||||
|
for _, v := range c.checkers { |
||||||
|
status = append(status, StatusResult{ |
||||||
|
Name: v.Name, |
||||||
|
CheckerStatus: v.getStatus(), |
||||||
|
}) |
||||||
|
} |
||||||
|
} else { |
||||||
|
for _, n := range name { |
||||||
|
if v, ok := c.checkers[n]; ok { |
||||||
|
status = append(status, StatusResult{ |
||||||
|
Name: v.Name, |
||||||
|
CheckerStatus: v.getStatus(), |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return status |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package health |
||||||
|
|
||||||
|
type Status int |
||||||
|
|
||||||
|
const ( |
||||||
|
StatusDown Status = iota |
||||||
|
StatusUp |
||||||
|
) |
||||||
|
|
||||||
|
type CheckerStatus struct { |
||||||
|
Status |
||||||
|
Detail interface{} |
||||||
|
Err error |
||||||
|
} |
Loading…
Reference in new issue