Skip to content

Commit

Permalink
bus: filter by alert severity
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisSchinnerl committed Feb 27, 2024
1 parent 97b017e commit 0ef1757
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 19 deletions.
55 changes: 37 additions & 18 deletions alerts/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,19 @@ type (
}

AlertsOpts struct {
Offset int
Limit int
Offset int
Limit int
Severity Severity
}

AlertsResponse struct {
Alerts []Alert `json:"alerts"`
HasMore bool `json:"hasMore"`
Total int `json:"total"`
Alerts []Alert `json:"alerts"`
HasMore bool `json:"hasMore"`
Total int `json:"total"`
TotalInfo int `json:"totalInfo"`
TotalWarning int `json:"totalWarning"`
TotalError int `json:"totalError"`
TotalCritical int `json:"totalCritical"`
}
)

Expand All @@ -93,15 +98,8 @@ func (s Severity) String() string {
}
}

// MarshalJSON implements the json.Marshaler interface.
func (s Severity) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`%q`, s.String())), nil
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (s *Severity) UnmarshalJSON(b []byte) error {
status := strings.Trim(string(b), `"`)
switch status {
func (s *Severity) LoadString(str string) error {
switch str {
case severityInfoStr:
*s = SeverityInfo
case severityWarningStr:
Expand All @@ -111,11 +109,21 @@ func (s *Severity) UnmarshalJSON(b []byte) error {
case severityCriticalStr:
*s = SeverityCritical
default:
return fmt.Errorf("unrecognized severity: %v", status)
return fmt.Errorf("unrecognized severity: %v", str)
}
return nil
}

// MarshalJSON implements the json.Marshaler interface.
func (s Severity) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`%q`, s.String())), nil
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (s *Severity) UnmarshalJSON(b []byte) error {
return s.LoadString(strings.Trim(string(b), `"`))
}

// RegisterAlert implements the Alerter interface.
func (m *Manager) RegisterAlert(ctx context.Context, alert Alert) error {
if alert.ID == (types.Hash256{}) {
Expand Down Expand Up @@ -176,9 +184,7 @@ func (m *Manager) Alerts(_ context.Context, opts AlertsOpts) (AlertsResponse, er
defer m.mu.Unlock()

offset, limit := opts.Offset, opts.Limit
resp := AlertsResponse{
Total: len(m.alerts),
}
resp := AlertsResponse{}

if offset >= len(m.alerts) {
return resp, nil
Expand All @@ -188,6 +194,19 @@ func (m *Manager) Alerts(_ context.Context, opts AlertsOpts) (AlertsResponse, er

alerts := make([]Alert, 0, len(m.alerts))
for _, a := range m.alerts {
resp.Total++
if a.Severity == SeverityInfo {
resp.TotalInfo++
} else if a.Severity == SeverityWarning {
resp.TotalWarning++
} else if a.Severity == SeverityError {
resp.TotalError++
} else if a.Severity == SeverityCritical {
resp.TotalCritical++
}
if opts.Severity != 0 && a.Severity != opts.Severity {
continue // filter by severity
}
alerts = append(alerts, a)
}
sort.Slice(alerts, func(i, j int) bool {
Expand Down
9 changes: 8 additions & 1 deletion bus/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -1739,15 +1739,22 @@ func (b *bus) handleGETAlerts(jc jape.Context) {
return
}
offset, limit := 0, -1
var severity alerts.Severity
if jc.DecodeForm("offset", &offset) != nil {
return
} else if jc.DecodeForm("limit", &limit) != nil {
return
} else if offset < 0 {
jc.Error(errors.New("offset must be non-negative"), http.StatusBadRequest)
return
} else if jc.DecodeForm("severity", &severity) != nil {
return
}
ar, err := b.alertMgr.Alerts(jc.Request.Context(), alerts.AlertsOpts{Offset: offset, Limit: limit})
ar, err := b.alertMgr.Alerts(jc.Request.Context(), alerts.AlertsOpts{
Offset: offset,
Limit: limit,
Severity: severity,
})
if jc.Check("failed to fetch alerts", err) != nil {
return
}
Expand Down
3 changes: 3 additions & 0 deletions bus/client/alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ func (c *Client) Alerts(ctx context.Context, opts alerts.AlertsOpts) (resp alert
if opts.Limit != 0 {
values.Set("limit", fmt.Sprint(opts.Limit))
}
if opts.Severity != 0 {
values.Set("severity", opts.Severity.String())
}
err = c.c.WithContext(ctx).GET("/alerts?"+values.Encode(), &resp)
return
}
Expand Down
38 changes: 38 additions & 0 deletions internal/testing/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1974,6 +1974,44 @@ func TestAlerts(t *testing.T) {
if len(foundAlerts) != 1 || foundAlerts[0].ID != alert2.ID {
t.Fatal("wrong alert")
}

// register more alerts
for severity := alerts.SeverityInfo; severity <= alerts.SeverityCritical; severity++ {
for j := 0; j < 3*int(severity); j++ {
tt.OK(b.RegisterAlert(context.Background(), alerts.Alert{
ID: frand.Entropy256(),
Severity: severity,
Message: "test",
Data: map[string]interface{}{
"origin": "test",
},
Timestamp: time.Now(),
}))
}
}
for severity := alerts.SeverityInfo; severity <= alerts.SeverityCritical; severity++ {
ar, err = b.Alerts(context.Background(), alerts.AlertsOpts{Severity: severity})
tt.OK(err)
if ar.Total != 32 {
t.Fatal("expected 32 alerts", ar.Total)
} else if ar.TotalInfo != 3 {
t.Fatal("expected 3 info alerts", ar.TotalInfo)
} else if ar.TotalWarning != 6 {
t.Fatal("expected 6 warning alerts", ar.TotalWarning)
} else if ar.TotalError != 9 {
t.Fatal("expected 9 error alerts", ar.TotalError)
} else if ar.TotalCritical != 14 {
t.Fatal("expected 14 critical alerts", ar.TotalCritical)
} else if severity == alerts.SeverityInfo && len(ar.Alerts) != ar.TotalInfo {
t.Fatalf("expected %v info alerts, got %v", ar.TotalInfo, len(ar.Alerts))
} else if severity == alerts.SeverityWarning && len(ar.Alerts) != ar.TotalWarning {
t.Fatalf("expected %v warning alerts, got %v", ar.TotalWarning, len(ar.Alerts))
} else if severity == alerts.SeverityError && len(ar.Alerts) != ar.TotalError {
t.Fatalf("expected %v error alerts, got %v", ar.TotalError, len(ar.Alerts))
} else if severity == alerts.SeverityCritical && len(ar.Alerts) != ar.TotalCritical {
t.Fatalf("expected %v critical alerts, got %v", ar.TotalCritical, len(ar.Alerts))
}
}
}

func TestMultipartUploads(t *testing.T) {
Expand Down

0 comments on commit 0ef1757

Please sign in to comment.