Skip to content

Commit ea817bb

Browse files
author
Julien
authored
Merge pull request #618 from grobinson-grafana/grobinson/add-status-at
Add StatusAt method for Alert struct
2 parents 0234594 + 506a12c commit ea817bb

File tree

2 files changed

+115
-7
lines changed

2 files changed

+115
-7
lines changed

model/alert.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,12 @@ func (a *Alert) ResolvedAt(ts time.Time) bool {
7575

7676
// Status returns the status of the alert.
7777
func (a *Alert) Status() AlertStatus {
78-
if a.Resolved() {
78+
return a.StatusAt(time.Now())
79+
}
80+
81+
// StatusAt returns the status of the alert at the given timestamp.
82+
func (a *Alert) StatusAt(ts time.Time) AlertStatus {
83+
if a.ResolvedAt(ts) {
7984
return AlertResolved
8085
}
8186
return AlertFiring
@@ -127,10 +132,30 @@ func (as Alerts) HasFiring() bool {
127132
return false
128133
}
129134

135+
// HasFiringAt returns true iff one of the alerts is not resolved
136+
// at the time ts.
137+
func (as Alerts) HasFiringAt(ts time.Time) bool {
138+
for _, a := range as {
139+
if !a.ResolvedAt(ts) {
140+
return true
141+
}
142+
}
143+
return false
144+
}
145+
130146
// Status returns StatusFiring iff at least one of the alerts is firing.
131147
func (as Alerts) Status() AlertStatus {
132148
if as.HasFiring() {
133149
return AlertFiring
134150
}
135151
return AlertResolved
136152
}
153+
154+
// StatusAt returns StatusFiring iff at least one of the alerts is firing
155+
// at the time ts.
156+
func (as Alerts) StatusAt(ts time.Time) AlertStatus {
157+
if as.HasFiringAt(ts) {
158+
return AlertFiring
159+
}
160+
return AlertResolved
161+
}

model/alert_test.go

+89-6
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ func TestAlert(t *testing.T) {
133133
t.Errorf("expected %s, but got %s", expected, actual)
134134
}
135135

136-
actualStatus := string(alert.Status())
137-
expectedStatus := "firing"
136+
actualStatus := alert.Status()
137+
expectedStatus := AlertStatus("firing")
138138

139139
if actualStatus != expectedStatus {
140140
t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus)
@@ -150,19 +150,55 @@ func TestAlert(t *testing.T) {
150150
EndsAt: ts2,
151151
}
152152

153+
if !alert.Resolved() {
154+
t.Error("expected alert to be resolved, but it was not")
155+
}
156+
153157
actual = fmt.Sprint(alert)
154158
expected = "[d181d0f][resolved]"
155159

156160
if actual != expected {
157161
t.Errorf("expected %s, but got %s", expected, actual)
158162
}
159163

160-
actualStatus = string(alert.Status())
164+
actualStatus = alert.Status()
161165
expectedStatus = "resolved"
162166

163167
if actualStatus != expectedStatus {
164168
t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus)
165169
}
170+
171+
// Verifying that ResolvedAt works for different times
172+
if alert.ResolvedAt(ts1) {
173+
t.Error("unexpected alert was resolved at start time")
174+
}
175+
if alert.ResolvedAt(ts2.Add(-time.Millisecond)) {
176+
t.Error("unexpected alert was resolved before it ended")
177+
}
178+
if !alert.ResolvedAt(ts2) {
179+
t.Error("expected alert to be resolved at end time")
180+
}
181+
if !alert.ResolvedAt(ts2.Add(time.Millisecond)) {
182+
t.Error("expected alert to be resolved after it ended")
183+
}
184+
185+
// Verifying that StatusAt works for different times
186+
actualStatus = alert.StatusAt(ts1)
187+
if actualStatus != "firing" {
188+
t.Errorf("expected alert to be firing at start time, but got %s", actualStatus)
189+
}
190+
actualStatus = alert.StatusAt(ts1.Add(-time.Millisecond))
191+
if actualStatus != "firing" {
192+
t.Errorf("expected alert to be firing before it ended, but got %s", actualStatus)
193+
}
194+
actualStatus = alert.StatusAt(ts2)
195+
if actualStatus != "resolved" {
196+
t.Errorf("expected alert to be resolved at end time, but got %s", actualStatus)
197+
}
198+
actualStatus = alert.StatusAt(ts2.Add(time.Millisecond))
199+
if actualStatus != "resolved" {
200+
t.Errorf("expected alert to be resolved after it ended, but got %s", actualStatus)
201+
}
166202
}
167203

168204
func TestSortAlerts(t *testing.T) {
@@ -228,18 +264,19 @@ func TestSortAlerts(t *testing.T) {
228264
}
229265

230266
func TestAlertsStatus(t *testing.T) {
267+
ts := time.Now()
231268
firingAlerts := Alerts{
232269
{
233270
Labels: LabelSet{
234271
"foo": "bar",
235272
},
236-
StartsAt: time.Now(),
273+
StartsAt: ts,
237274
},
238275
{
239276
Labels: LabelSet{
240277
"bar": "baz",
241278
},
242-
StartsAt: time.Now(),
279+
StartsAt: ts,
243280
},
244281
}
245282

@@ -250,7 +287,12 @@ func TestAlertsStatus(t *testing.T) {
250287
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
251288
}
252289

253-
ts := time.Now()
290+
actualStatus = firingAlerts.StatusAt(ts)
291+
if actualStatus != expectedStatus {
292+
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
293+
}
294+
295+
ts = time.Now()
254296
resolvedAlerts := Alerts{
255297
{
256298
Labels: LabelSet{
@@ -270,7 +312,48 @@ func TestAlertsStatus(t *testing.T) {
270312

271313
actualStatus = resolvedAlerts.Status()
272314
expectedStatus = AlertResolved
315+
if actualStatus != expectedStatus {
316+
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
317+
}
318+
319+
actualStatus = resolvedAlerts.StatusAt(ts)
320+
expectedStatus = AlertResolved
321+
if actualStatus != expectedStatus {
322+
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
323+
}
273324

325+
ts = time.Now()
326+
mixedAlerts := Alerts{
327+
{
328+
Labels: LabelSet{
329+
"foo": "bar",
330+
},
331+
StartsAt: ts.Add(-1 * time.Minute),
332+
EndsAt: ts.Add(5 * time.Minute),
333+
},
334+
{
335+
Labels: LabelSet{
336+
"bar": "baz",
337+
},
338+
StartsAt: ts.Add(-1 * time.Minute),
339+
EndsAt: ts,
340+
},
341+
}
342+
343+
actualStatus = mixedAlerts.Status()
344+
expectedStatus = AlertFiring
345+
if actualStatus != expectedStatus {
346+
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
347+
}
348+
349+
actualStatus = mixedAlerts.StatusAt(ts)
350+
expectedStatus = AlertFiring
351+
if actualStatus != expectedStatus {
352+
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
353+
}
354+
355+
actualStatus = mixedAlerts.StatusAt(ts.Add(5 * time.Minute))
356+
expectedStatus = AlertResolved
274357
if actualStatus != expectedStatus {
275358
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
276359
}

0 commit comments

Comments
 (0)