-
Notifications
You must be signed in to change notification settings - Fork 669
/
health.go
132 lines (111 loc) · 3.16 KB
/
health.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package health
import (
"encoding/json"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/ava-labs/avalanchego/utils/logging"
)
var _ Health = &health{}
// Health defines the full health service interface for registering, reporting
// and refreshing health checks.
type Health interface {
Registerer
Reporter
Start(freq time.Duration)
Stop()
}
// Registerer defines how to register new components to check the health of.
type Registerer interface {
RegisterReadinessCheck(name string, checker Checker) error
RegisterHealthCheck(name string, checker Checker) error
RegisterLivenessCheck(name string, checker Checker) error
}
// Reporter returns the current health status.
type Reporter interface {
Readiness() (map[string]Result, bool)
Health() (map[string]Result, bool)
Liveness() (map[string]Result, bool)
}
type health struct {
log logging.Logger
readiness *worker
health *worker
liveness *worker
}
func New(log logging.Logger, registerer prometheus.Registerer) (Health, error) {
readinessWorker, err := newWorker("readiness", registerer)
if err != nil {
return nil, err
}
healthWorker, err := newWorker("health", registerer)
if err != nil {
return nil, err
}
livenessWorker, err := newWorker("liveness", registerer)
return &health{
log: log,
readiness: readinessWorker,
health: healthWorker,
liveness: livenessWorker,
}, err
}
func (h *health) RegisterReadinessCheck(name string, checker Checker) error {
return h.readiness.RegisterMonotonicCheck(name, checker)
}
func (h *health) RegisterHealthCheck(name string, checker Checker) error {
return h.health.RegisterCheck(name, checker)
}
func (h *health) RegisterLivenessCheck(name string, checker Checker) error {
return h.liveness.RegisterCheck(name, checker)
}
func (h *health) Readiness() (map[string]Result, bool) {
results, healthy := h.readiness.Results()
if healthy {
return results, healthy
}
resultsJSON, err := json.Marshal(results)
if err == nil {
h.log.Warn("Failing readiness check: %s", string(resultsJSON))
} else {
h.log.Error("Failed to marshal failing readiness check: %s", err)
}
return results, false
}
func (h *health) Health() (map[string]Result, bool) {
results, healthy := h.health.Results()
if healthy {
return results, healthy
}
resultsJSON, err := json.Marshal(results)
if err == nil {
h.log.Warn("Failing health check: %s", string(resultsJSON))
} else {
h.log.Error("Failed to marshal failing health check: %s", err)
}
return results, false
}
func (h *health) Liveness() (map[string]Result, bool) {
results, healthy := h.liveness.Results()
if healthy {
return results, healthy
}
resultsJSON, err := json.Marshal(results)
if err == nil {
h.log.Warn("Failing liveness check: %s", string(resultsJSON))
} else {
h.log.Error("Failed to marshal failing liveness check: %s", err)
}
return results, false
}
func (h *health) Start(freq time.Duration) {
h.readiness.Start(freq)
h.health.Start(freq)
h.liveness.Start(freq)
}
func (h *health) Stop() {
h.readiness.Stop()
h.health.Stop()
h.liveness.Stop()
}