-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsummary.go
149 lines (134 loc) · 3.96 KB
/
summary.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
package libhealth
import (
"net/http"
"time"
"github.com/emirpasic/gods/sets/hashset"
)
// Summary is for representing the result of running multiple Checker instances
// such as the ones kept by a Dependencies. This object is intended to be used
// by a Dependencies for generating specified JSON output.
type Summary struct {
executed time.Time
results []Result
}
// NewSummary will create a new Summary for a list of Health responses.
func NewSummary(executed time.Time, results []Result) Summary {
return Summary{
executed: executed,
results: results,
}
}
// Result represents the final result of a HealthChecker. It contains
// all the information needed before being consumed by a robot.
type Result struct {
Health
docurl string
desc string
lastGood time.Time
period time.Duration
name string
}
// Executed returns the time at which s was generated by initiating
// the checks it represents.
func (s Summary) Executed() time.Time {
return s.executed
}
// Overall will return the combined downgraded Status of all of the Health instances.
// This state depends on both the check status and the urgency of each of the Health instances.
func (s Summary) Overall() Status {
if len(s.results) == 0 {
return OK
}
lowest := OK
for _, d := range s.results {
h := d.Health
s := h.Status
downgraded := h.Urgency.DowngradeWith(lowest, s)
if downgraded.SameOrWorseThan(lowest) {
lowest = downgraded
}
}
return lowest
}
// Status will return the combined downgraded Status of all of the Health instances identified by name
// The state does NOT depend on the urgency of each of the Health instances
func (s Summary) Status(names ...string) Status {
if len(s.results) == 0 {
return OK
}
lowest := OK
set := hashset.New(variadic(names)...)
for _, d := range s.results {
if !set.Contains(d.name) {
continue
}
s := d.Health.Status
if s.SameOrWorseThan(lowest) {
lowest = s
}
}
return lowest
}
// StatusWithUrgency will return the combined downgraded Status of all of the Health instances identified by name
// This status depends on both the check status and the urgency of each of the Health instances.
func (s Summary) StatusWithUrgency(names ...string) Status {
if len(s.results) == 0 {
return OK
}
lowest := OK
set := hashset.New(variadic(names)...)
for _, d := range s.results {
if !set.Contains(d.name) {
continue
}
h := d.Health
s := h.Status
downgraded := h.Urgency.DowngradeWith(lowest, s)
if downgraded.SameOrWorseThan(lowest) {
lowest = downgraded
}
}
return lowest
}
// Duration is a method provided to determine the total
// length of time it took to compute a Summary - that is how long it took to run
// a set of Checkers and produce results.
func (s Summary) Duration() time.Duration {
earliestStart := time.Date(9999, 0, 0, 0, 0, 0, 0, time.UTC)
latestFinish := time.Date(2000, 0, 0, 0, 0, 0, 0, time.UTC)
for _, d := range s.results {
startTime := d.Health.Time
endTime := startTime.Add(d.Health.Duration)
if startTime.Before(earliestStart) {
earliestStart = startTime
}
if endTime.After(latestFinish) {
latestFinish = endTime
}
}
return latestFinish.Sub(earliestStart)
}
// ComputeStatusCode returns the HTTP status code representative of the status.
// The public info endpoints return HTTP 500 internal server error if the component is in outage.
// Otherwise, any lessor status returns HTTP 200 ok.
// The private endpoints conversely return a HTTP 200 ok if and only if the overall state is ok.
// Any unhealthy state will return an HTTP 500 internal server error.
func ComputeStatusCode(info bool, s Summary) int {
if info {
if s.Overall() == OUTAGE {
return http.StatusInternalServerError
}
return http.StatusOK
}
if s.Overall() == OK {
return http.StatusOK
}
return http.StatusInternalServerError
}
func variadic(slice []string) []interface{} {
variadic := make([]interface{}, 0, len(slice))
for _, s := range slice {
variadic = append(variadic, s)
}
return variadic
}