-
Notifications
You must be signed in to change notification settings - Fork 1
/
health.go
153 lines (127 loc) · 3.37 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package hexa
import (
"context"
)
type ReadinessStatus string
const (
StatusReady ReadinessStatus = "READY"
StatusUnReady ReadinessStatus = "UNREADY"
)
type LivenessStatus string
const (
StatusAlive LivenessStatus = "ALIVE"
StatusDead LivenessStatus = "DEAD"
)
type (
LivenessResult struct {
Id string `json:"id"`
Status LivenessStatus
}
ReadinessResult struct {
Id string `json:"id"`
Status ReadinessStatus
}
HealthStatus struct {
Id string `json:"id"`
Alive LivenessStatus `json:"alive"`
Ready ReadinessStatus `json:"ready"`
Tags map[string]string `json:"tags,omitempty"`
}
)
type HealthReport struct {
Alive LivenessStatus `json:"alive"`
Ready ReadinessStatus `json:"ready"`
Statuses []HealthStatus `json:"statuses"`
}
type Health interface {
HealthIdentifier() string
LivenessStatus(ctx context.Context) LivenessStatus
ReadinessStatus(ctx context.Context) ReadinessStatus
HealthStatus(ctx context.Context) HealthStatus
}
type HealthReporter interface {
AddLivenessChecks(l ...Health) HealthReporter
AddReadinessChecks(l ...Health) HealthReporter
AddStatusChecks(l ...Health) HealthReporter
AddToChecks(l ...Health) HealthReporter
LivenessStatus(ctx context.Context) LivenessStatus
ReadinessStatus(ctx context.Context) ReadinessStatus
HealthReport(ctx context.Context) HealthReport
}
type healthReporter struct {
livenssCheck []Health
readinessCheck []Health
statusCheck []Health
}
func NewHealthReporter() HealthReporter {
return &healthReporter{
livenssCheck: []Health{},
readinessCheck: []Health{},
statusCheck: []Health{},
}
}
func (h *healthReporter) AddLivenessChecks(l ...Health) HealthReporter {
h.livenssCheck = append(h.livenssCheck, l...)
return h
}
func (h *healthReporter) AddReadinessChecks(l ...Health) HealthReporter {
h.readinessCheck = append(h.readinessCheck, l...)
return h
}
func (h *healthReporter) AddStatusChecks(l ...Health) HealthReporter {
h.statusCheck = append(h.statusCheck, l...)
return h
}
func (h *healthReporter) AddToChecks(l ...Health) HealthReporter {
return h.AddLivenessChecks(l...).AddReadinessChecks(l...).AddStatusChecks(l...)
}
func (h healthReporter) LivenessStatus(ctx context.Context) LivenessStatus {
for _, health := range h.livenssCheck {
if st := health.LivenessStatus(ctx); st != StatusAlive {
return st
}
}
return StatusAlive
}
func (h healthReporter) ReadinessStatus(ctx context.Context) ReadinessStatus {
for _, health := range h.readinessCheck {
if st := health.ReadinessStatus(ctx); st != StatusReady {
return st
}
}
return StatusReady
}
func (h healthReporter) HealthReport(ctx context.Context) HealthReport {
l := HealthCheck(ctx, h.statusCheck...)
return HealthReport{
Alive: AliveStatus(l...),
Ready: ReadyStatus(l...),
Statuses: l,
}
}
// Assertion
var _ HealthReporter = &healthReporter{}
func HealthCheck(ctx context.Context, l ...Health) []HealthStatus {
// TODO: check using go routines
r := make([]HealthStatus, len(l))
for i, health := range l {
r[i] = health.HealthStatus(ctx)
}
return r
}
func AliveStatus(l ...HealthStatus) LivenessStatus {
for _, s := range l {
if s.Alive != StatusAlive {
return StatusDead
}
}
return StatusAlive
}
func ReadyStatus(l ...HealthStatus) ReadinessStatus {
for _, s := range l {
if s.Ready != StatusReady {
return StatusUnReady
}
}
return StatusReady
}