diff --git a/docs/querying/api.md b/docs/querying/api.md index e9cce44c2..7eada565a 100644 --- a/docs/querying/api.md +++ b/docs/querying/api.md @@ -406,6 +406,7 @@ $ curl http://localhost:9090/api/v1/rules "summary": "High request latency" }, "duration": 600, + "health": "ok", "labels": { "severity": "page" }, @@ -414,6 +415,7 @@ $ curl http://localhost:9090/api/v1/rules "type": "alerting" }, { + "health": "ok", "name": "job:http_inprogress_requests:sum", "query": "sum(http_inprogress_requests) by (job)", "type": "recording" diff --git a/web/api/v1/api.go b/web/api/v1/api.go index 3ffbc9964..12893b028 100644 --- a/web/api/v1/api.go +++ b/web/api/v1/api.go @@ -655,20 +655,24 @@ type RuleGroup struct { type rule interface{} type alertingRule struct { - Name string `json:"name"` - Query string `json:"query"` - Duration float64 `json:"duration"` - Labels labels.Labels `json:"labels"` - Annotations labels.Labels `json:"annotations"` - Alerts []*Alert `json:"alerts"` + Name string `json:"name"` + Query string `json:"query"` + Duration float64 `json:"duration"` + Labels labels.Labels `json:"labels"` + Annotations labels.Labels `json:"annotations"` + Alerts []*Alert `json:"alerts"` + Health rules.RuleHealth `json:"health"` + LastError string `json:"lastError,omitempty"` // Type of an alertingRule is always "alerting". Type string `json:"type"` } type recordingRule struct { - Name string `json:"name"` - Query string `json:"query"` - Labels labels.Labels `json:"labels,omitempty"` + Name string `json:"name"` + Query string `json:"query"` + Labels labels.Labels `json:"labels,omitempty"` + Health rules.RuleHealth `json:"health"` + LastError string `json:"lastError,omitempty"` // Type of a recordingRule is always "recording". Type string `json:"type"` } @@ -687,6 +691,11 @@ func (api *API) rules(r *http.Request) (interface{}, *apiError, func()) { for _, r := range grp.Rules() { var enrichedRule rule + lastError := "" + if r.LastError() != nil { + lastError = r.LastError().Error() + } + switch rule := r.(type) { case *rules.AlertingRule: enrichedRule = alertingRule{ @@ -696,14 +705,18 @@ func (api *API) rules(r *http.Request) (interface{}, *apiError, func()) { Labels: rule.Labels(), Annotations: rule.Annotations(), Alerts: rulesAlertsToAPIAlerts(rule.ActiveAlerts()), + Health: rule.Health(), + LastError: lastError, Type: "alerting", } case *rules.RecordingRule: enrichedRule = recordingRule{ - Name: rule.Name(), - Query: rule.Query().String(), - Labels: rule.Labels(), - Type: "recording", + Name: rule.Name(), + Query: rule.Query().String(), + Labels: rule.Labels(), + Health: rule.Health(), + LastError: lastError, + Type: "recording", } default: err := fmt.Errorf("failed to assert type of rule '%v'", rule.Name()) diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 53ee38987..b9253a475 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -681,6 +681,7 @@ func testEndpoints(t *testing.T, api *API, testLabelAPI bool) { Labels: labels.Labels{}, Annotations: labels.Labels{}, Alerts: []*Alert{}, + Health: "unknown", Type: "alerting", }, alertingRule{ @@ -690,12 +691,14 @@ func testEndpoints(t *testing.T, api *API, testLabelAPI bool) { Labels: labels.Labels{}, Annotations: labels.Labels{}, Alerts: []*Alert{}, + Health: "unknown", Type: "alerting", }, recordingRule{ Name: "recording-rule-1", Query: "vector(1)", Labels: labels.Labels{}, + Health: "unknown", Type: "recording", }, },