@@ -15,11 +15,15 @@ var (
15
15
checkMap = make (map [string ]Config )
16
16
)
17
17
18
+ // Status type represents health status
19
+ type Status string
20
+
21
+ // Possible health statuses
18
22
const (
19
- statusOK = "OK"
20
- statusPartiallyAvailable = "Partially Available"
21
- statusUnavailable = "Unavailable"
22
- failureTimeout = "Timeout during health check"
23
+ StatusOK Status = "OK"
24
+ StatusPartiallyAvailable Status = "Partially Available"
25
+ StatusUnavailable Status = "Unavailable"
26
+ StatusTimeout Status = "Timeout during health check"
23
27
)
24
28
25
29
type (
41
45
// Check represents the health check response.
42
46
Check struct {
43
47
// Status is the check status.
44
- Status string `json:"status"`
48
+ Status Status `json:"status"`
45
49
// Timestamp is the time in which the check occurred.
46
50
Timestamp time.Time `json:"timestamp"`
47
51
// Failures holds the failed checks along with their messages.
@@ -100,10 +104,30 @@ func Handler() http.Handler {
100
104
101
105
// HandlerFunc is the HTTP handler function.
102
106
func HandlerFunc (w http.ResponseWriter , r * http.Request ) {
107
+ c := Measure ()
108
+
109
+ w .Header ().Set ("Content-Type" , "application/json" )
110
+ data , err := json .Marshal (c )
111
+ if err != nil {
112
+ w .WriteHeader (http .StatusInternalServerError )
113
+ http .Error (w , err .Error (), http .StatusInternalServerError )
114
+ return
115
+ }
116
+
117
+ code := http .StatusOK
118
+ if c .Status == StatusUnavailable {
119
+ code = http .StatusServiceUnavailable
120
+ }
121
+ w .WriteHeader (code )
122
+ w .Write (data )
123
+ }
124
+
125
+ // Measure runs all the registered health checks and returns summary status
126
+ func Measure () Check {
103
127
mu .Lock ()
104
128
defer mu .Unlock ()
105
129
106
- status := statusOK
130
+ status := StatusOK
107
131
total := len (checkMap )
108
132
failures := make (map [string ]string )
109
133
resChan := make (chan checkResponse , total )
@@ -113,12 +137,14 @@ func HandlerFunc(w http.ResponseWriter, r *http.Request) {
113
137
114
138
go func () {
115
139
defer close (resChan )
140
+
116
141
wg .Wait ()
117
142
}()
118
143
119
144
for _ , c := range checkMap {
120
145
go func (c Config ) {
121
146
defer wg .Done ()
147
+
122
148
select {
123
149
case resChan <- checkResponse {c .Name , c .SkipOnErr , c .Check ()}:
124
150
default :
@@ -129,34 +155,20 @@ func HandlerFunc(w http.ResponseWriter, r *http.Request) {
129
155
for {
130
156
select {
131
157
case <- time .After (c .Timeout ):
132
- failures [c .Name ] = failureTimeout
133
- setStatus ( & status , c .SkipOnErr )
158
+ failures [c .Name ] = string ( StatusTimeout )
159
+ status = getAvailability ( status , c .SkipOnErr )
134
160
break loop
135
161
case res := <- resChan :
136
162
if res .err != nil {
137
163
failures [res .name ] = res .err .Error ()
138
- setStatus ( & status , res .skipOnErr )
164
+ status = getAvailability ( status , res .skipOnErr )
139
165
}
140
166
break loop
141
167
}
142
168
}
143
169
}
144
170
145
- w .Header ().Set ("Content-Type" , "application/json" )
146
- c := newCheck (status , failures )
147
- data , err := json .Marshal (c )
148
- if err != nil {
149
- w .WriteHeader (http .StatusInternalServerError )
150
- http .Error (w , err .Error (), http .StatusInternalServerError )
151
- return
152
- }
153
-
154
- code := http .StatusOK
155
- if status == statusUnavailable {
156
- code = http .StatusServiceUnavailable
157
- }
158
- w .WriteHeader (code )
159
- w .Write (data )
171
+ return newCheck (status , failures )
160
172
}
161
173
162
174
// Reset unregisters all previously set check configs
@@ -167,9 +179,9 @@ func Reset() {
167
179
checkMap = make (map [string ]Config )
168
180
}
169
181
170
- func newCheck (status string , failures map [string ]string ) Check {
182
+ func newCheck (s Status , failures map [string ]string ) Check {
171
183
return Check {
172
- Status : status ,
184
+ Status : s ,
173
185
Timestamp : time .Now (),
174
186
Failures : failures ,
175
187
System : newSystemMetrics (),
@@ -189,10 +201,10 @@ func newSystemMetrics() System {
189
201
}
190
202
}
191
203
192
- func setStatus (status * string , skipOnErr bool ) {
193
- if skipOnErr && * status != statusUnavailable {
194
- * status = statusPartiallyAvailable
195
- } else {
196
- * status = statusUnavailable
204
+ func getAvailability (s Status , skipOnErr bool ) Status {
205
+ if skipOnErr && s != StatusUnavailable {
206
+ return StatusPartiallyAvailable
197
207
}
208
+
209
+ return StatusUnavailable
198
210
}
0 commit comments