-
Notifications
You must be signed in to change notification settings - Fork 10
/
healthchecks.go
145 lines (117 loc) · 3.37 KB
/
healthchecks.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
package healthchecks
import (
"encoding/json"
"fmt"
)
/* Health checks */
type StatusResponse struct {
Status string `json:"status"`
}
type StatusEndpoint struct {
Name string
Slug string
Type string
IsTraversable bool
StatusCheck StatusCheck
TraverseCheck TraverseCheck
}
type Status struct {
Description string `json:"description"`
Result AlertLevel `json:"result"`
Details string `json:"details"`
}
type AlertLevel string
const (
OK AlertLevel = "OK"
WARNING AlertLevel = "WARN"
CRITICAL AlertLevel = "CRIT"
)
type StatusList struct {
StatusList []Status
}
// A status check for a dependency.
type StatusCheck interface {
// Checks the status of some dependency.
CheckStatus(name string) StatusList
}
type JsonResponse interface {
}
// TraverseCheck enables a traversal in the service graph.
type TraverseCheck interface {
/* Traverse to the next level in the service graph. This function should be implemented by
SDKs or clients that want to enable service traversal.
This function should:
1. Call the dependent service and pass along both 'traversalPath' and 'action' params
2. Return the response from the dependent service without modifying it */
Traverse(traversalPath []string, action string) (string, error)
}
func SerializeStatusList(s StatusList, apiVersion APIVersion) string {
if apiVersion == APIV2 {
statusListJSONResponse := translateStatusListV2(s)
statusListJSON, err := json.Marshal(statusListJSONResponse)
if err != nil {
details := fmt.Sprintf("Error serializing StatusList: %v error: %s apiVersion: %v", s, err, apiVersion)
fmt.Print(details)
return fmt.Sprintf(`{"description":"Invalid StatusList","result":"CRIT","details":"%s"}`, details)
}
return string(statusListJSON)
}
statusListJSONResponse := translateStatusList(s)
statusListJSON, err := json.Marshal(statusListJSONResponse)
if err != nil {
details := fmt.Sprintf("Error serializing StatusList: %v error: %s apiVersion: %v", s, err, apiVersion)
fmt.Print(details)
return fmt.Sprintf(`["CRIT",{"description":"Invalid StatusList","result":"CRIT","details":"%s"}]`, details)
}
return string(statusListJSON)
}
func translateStatusList(s StatusList) []JsonResponse {
if len(s.StatusList) <= 0 {
return []JsonResponse{
CRITICAL,
Status{
Description: "Invalid status response",
Result: CRITICAL,
Details: "StatusList empty",
},
}
}
r := s.StatusList[0]
if r.Result == OK {
return []JsonResponse{
OK,
}
}
return []JsonResponse{
r.Result,
r,
}
}
func translateStatusListV2(s StatusList) JsonResponse {
if len(s.StatusList) <= 0 {
return Status{
Description: "Invalid status response",
Result: CRITICAL,
Details: "StatusList empty",
}
}
return s.StatusList[0]
}
func ExecuteStatusCheck(s *StatusEndpoint, apiVersion APIVersion) string {
result := s.StatusCheck.CheckStatus(s.Name)
return SerializeStatusList(result, apiVersion)
}
// Find the StatusEndpoint given the slug (aka Status Path) to search for.
// The function will return the StatusEndpoint if found. If not found, returns nil
// If the slug is empty, it will also return nil
func FindStatusEndpoint(statusEndpoints []StatusEndpoint, slug string) *StatusEndpoint {
if slug == "" {
return nil
}
for _, s := range statusEndpoints {
if slug == s.Slug {
return &s
}
}
return nil
}