Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add StatusAt method for Alert struct #618

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 26 additions & 1 deletion model/alert.go
Expand Up @@ -75,7 +75,12 @@ func (a *Alert) ResolvedAt(ts time.Time) bool {

// Status returns the status of the alert.
func (a *Alert) Status() AlertStatus {
if a.Resolved() {
return a.StatusAt(time.Now())
}

// StatusAt returns the status of the alert at the given timestamp.
func (a *Alert) StatusAt(ts time.Time) AlertStatus {
if a.ResolvedAt(ts) {
return AlertResolved
}
return AlertFiring
Expand Down Expand Up @@ -127,10 +132,30 @@ func (as Alerts) HasFiring() bool {
return false
}

// HasFiringAt returns true iff one of the alerts is not resolved
// at the time ts.
func (as Alerts) HasFiringAt(ts time.Time) bool {
for _, a := range as {
if !a.ResolvedAt(ts) {
return true
}
}
return false
}

// Status returns StatusFiring iff at least one of the alerts is firing.
func (as Alerts) Status() AlertStatus {
if as.HasFiring() {
return AlertFiring
}
return AlertResolved
}

// StatusAt returns StatusFiring iff at least one of the alerts is firing
// at the time ts.
func (as Alerts) StatusAt(ts time.Time) AlertStatus {
if as.HasFiringAt(ts) {
return AlertFiring
}
return AlertResolved
}
95 changes: 89 additions & 6 deletions model/alert_test.go
Expand Up @@ -133,8 +133,8 @@ func TestAlert(t *testing.T) {
t.Errorf("expected %s, but got %s", expected, actual)
}

actualStatus := string(alert.Status())
expectedStatus := "firing"
actualStatus := alert.Status()
expectedStatus := AlertStatus("firing")

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

if !alert.Resolved() {
t.Error("expected alert to be resolved, but it was not")
}

actual = fmt.Sprint(alert)
expected = "[d181d0f][resolved]"

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

actualStatus = string(alert.Status())
actualStatus = alert.Status()
expectedStatus = "resolved"

if actualStatus != expectedStatus {
t.Errorf("expected alertStatus %s, but got %s", expectedStatus, actualStatus)
}

// Verifying that ResolvedAt works for different times
if alert.ResolvedAt(ts1) {
t.Error("unexpected alert was resolved at start time")
}
if alert.ResolvedAt(ts2.Add(-time.Millisecond)) {
t.Error("unexpected alert was resolved before it ended")
}
if !alert.ResolvedAt(ts2) {
t.Error("expected alert to be resolved at end time")
}
if !alert.ResolvedAt(ts2.Add(time.Millisecond)) {
t.Error("expected alert to be resolved after it ended")
}

// Verifying that StatusAt works for different times
actualStatus = alert.StatusAt(ts1)
if actualStatus != "firing" {
t.Errorf("expected alert to be firing at start time, but got %s", actualStatus)
}
actualStatus = alert.StatusAt(ts1.Add(-time.Millisecond))
if actualStatus != "firing" {
t.Errorf("expected alert to be firing before it ended, but got %s", actualStatus)
}
actualStatus = alert.StatusAt(ts2)
if actualStatus != "resolved" {
t.Errorf("expected alert to be resolved at end time, but got %s", actualStatus)
}
actualStatus = alert.StatusAt(ts2.Add(time.Millisecond))
if actualStatus != "resolved" {
t.Errorf("expected alert to be resolved after it ended, but got %s", actualStatus)
}
}

func TestSortAlerts(t *testing.T) {
Expand Down Expand Up @@ -228,18 +264,19 @@ func TestSortAlerts(t *testing.T) {
}

func TestAlertsStatus(t *testing.T) {
ts := time.Now()
firingAlerts := Alerts{
{
Labels: LabelSet{
"foo": "bar",
},
StartsAt: time.Now(),
StartsAt: ts,
},
{
Labels: LabelSet{
"bar": "baz",
},
StartsAt: time.Now(),
StartsAt: ts,
},
}

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

ts := time.Now()
actualStatus = firingAlerts.StatusAt(ts)
if actualStatus != expectedStatus {
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
}

ts = time.Now()
resolvedAlerts := Alerts{
{
Labels: LabelSet{
Expand All @@ -270,7 +312,48 @@ func TestAlertsStatus(t *testing.T) {

actualStatus = resolvedAlerts.Status()
expectedStatus = AlertResolved
if actualStatus != expectedStatus {
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
}

actualStatus = resolvedAlerts.StatusAt(ts)
expectedStatus = AlertResolved
if actualStatus != expectedStatus {
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
}

ts = time.Now()
mixedAlerts := Alerts{
{
Labels: LabelSet{
"foo": "bar",
},
StartsAt: ts.Add(-1 * time.Minute),
EndsAt: ts.Add(5 * time.Minute),
},
{
Labels: LabelSet{
"bar": "baz",
},
StartsAt: ts.Add(-1 * time.Minute),
EndsAt: ts,
},
}

actualStatus = mixedAlerts.Status()
expectedStatus = AlertFiring
if actualStatus != expectedStatus {
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
}

actualStatus = mixedAlerts.StatusAt(ts)
expectedStatus = AlertFiring
if actualStatus != expectedStatus {
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
}

actualStatus = mixedAlerts.StatusAt(ts.Add(5 * time.Minute))
expectedStatus = AlertResolved
if actualStatus != expectedStatus {
t.Errorf("expected status %s, but got %s", expectedStatus, actualStatus)
}
Expand Down