diff --git a/health/checker.go b/health/checker.go new file mode 100644 index 000000000..0206d0c81 --- /dev/null +++ b/health/checker.go @@ -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 +} diff --git a/health/health.go b/health/health.go new file mode 100644 index 000000000..7484333a5 --- /dev/null +++ b/health/health.go @@ -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 +} diff --git a/health/status.go b/health/status.go new file mode 100644 index 000000000..e7b544143 --- /dev/null +++ b/health/status.go @@ -0,0 +1,14 @@ +package health + +type Status int + +const ( + StatusDown Status = iota + StatusUp +) + +type CheckerStatus struct { + Status + Detail interface{} + Err error +}