mirror of
https://github.com/grafana/grafana.git
synced 2024-11-28 03:34:15 -06:00
Alerting: Add endpoint for querying state history (#62166)
* Define endpoint and generate * Wire up and register endpoint * Cleanup, define authorization * Forgot the leading slash * Wire up query and SignedInUser * Wire up timerange query params * Add todo for label queries * Drop comment * Update path to rules subtree
This commit is contained in:
parent
2f218ab928
commit
6ad1cfef38
@ -84,6 +84,7 @@ type API struct {
|
||||
AlertsRouter *sender.AlertsRouter
|
||||
EvaluatorFactory eval.EvaluatorFactory
|
||||
FeatureManager featuremgmt.FeatureToggles
|
||||
Historian Historian
|
||||
|
||||
AppUrl *url.URL
|
||||
}
|
||||
@ -152,6 +153,11 @@ func (api *API) RegisterAPIEndpoints(m *metrics.API) {
|
||||
muteTimings: api.MuteTimings,
|
||||
alertRules: api.AlertRules,
|
||||
}), m)
|
||||
|
||||
api.RegisterHistoryApiEndpoints(NewStateHistoryApi(&HistorySrv{
|
||||
logger: logger,
|
||||
hist: api.Historian,
|
||||
}), m)
|
||||
}
|
||||
|
||||
func (api *API) Usage(ctx context.Context, scopeParams *quota.ScopeParameters) (*quota.Map, error) {
|
||||
|
40
pkg/services/ngalert/api/api_ruler_history.go
Normal file
40
pkg/services/ngalert/api/api_ruler_history.go
Normal file
@ -0,0 +1,40 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
)
|
||||
|
||||
type Historian interface {
|
||||
QueryStates(ctx context.Context, query models.HistoryQuery) (*data.Frame, error)
|
||||
}
|
||||
|
||||
type HistorySrv struct {
|
||||
logger log.Logger
|
||||
hist Historian
|
||||
}
|
||||
|
||||
func (srv *HistorySrv) RouteQueryStateHistory(c *contextmodel.ReqContext) response.Response {
|
||||
from := c.QueryInt64("from")
|
||||
to := c.QueryInt64("to")
|
||||
query := models.HistoryQuery{
|
||||
RuleUID: c.Query("ruleUID"),
|
||||
OrgID: c.OrgID,
|
||||
SignedInUser: c.SignedInUser,
|
||||
From: time.Unix(from, 0),
|
||||
To: time.Unix(to, 0),
|
||||
Labels: map[string]string{}, // TODO, not supported by all backends yet.
|
||||
}
|
||||
frame, err := srv.hist.QueryStates(c.Req.Context(), query)
|
||||
if err != nil {
|
||||
return ErrResp(http.StatusInternalServerError, err, "")
|
||||
}
|
||||
return response.JSON(http.StatusOK, frame)
|
||||
}
|
@ -58,6 +58,10 @@ func (api *API) authorize(method, path string) web.Handler {
|
||||
ac.EvalPermission(ac.ActionAlertingRuleCreate, scope),
|
||||
ac.EvalPermission(ac.ActionAlertingRuleDelete, scope),
|
||||
)
|
||||
// Grafana rule state history paths
|
||||
case http.MethodGet + "/api/v1/rules/history":
|
||||
fallback = middleware.ReqSignedIn
|
||||
eval = ac.EvalPermission(ac.ActionAlertingRuleRead)
|
||||
|
||||
// Grafana, Prometheus-compatible Paths
|
||||
case http.MethodGet + "/api/prometheus/grafana/api/v1/rules":
|
||||
|
@ -49,7 +49,7 @@ func TestAuthorize(t *testing.T) {
|
||||
}
|
||||
paths[p] = methods
|
||||
}
|
||||
require.Len(t, paths, 44)
|
||||
require.Len(t, paths, 45)
|
||||
|
||||
ac := acmock.New()
|
||||
api := &API{AccessControl: ac}
|
||||
|
40
pkg/services/ngalert/api/generated_base_api_history.go
Normal file
40
pkg/services/ngalert/api/generated_base_api_history.go
Normal file
@ -0,0 +1,40 @@
|
||||
/*Package api contains base API implementation of unified alerting
|
||||
*
|
||||
*Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
|
||||
*
|
||||
*Do not manually edit these files, please find ngalert/api/swagger-codegen/ for commands on how to generate them.
|
||||
*/
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
||||
)
|
||||
|
||||
type HistoryApi interface {
|
||||
RouteGetStateHistory(*contextmodel.ReqContext) response.Response
|
||||
}
|
||||
|
||||
func (f *HistoryApiHandler) RouteGetStateHistory(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.handleRouteGetStateHistory(ctx)
|
||||
}
|
||||
|
||||
func (api *API) RegisterHistoryApiEndpoints(srv HistoryApi, m *metrics.API) {
|
||||
api.RouteRegister.Group("", func(group routing.RouteRegister) {
|
||||
group.Get(
|
||||
toMacaronPath("/api/v1/rules/history"),
|
||||
api.authorize(http.MethodGet, "/api/v1/rules/history"),
|
||||
metrics.Instrument(
|
||||
http.MethodGet,
|
||||
"/api/v1/rules/history",
|
||||
srv.RouteGetStateHistory,
|
||||
m,
|
||||
),
|
||||
)
|
||||
}, middleware.ReqSignedIn)
|
||||
}
|
20
pkg/services/ngalert/api/ruler_history.go
Normal file
20
pkg/services/ngalert/api/ruler_history.go
Normal file
@ -0,0 +1,20 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
)
|
||||
|
||||
type HistoryApiHandler struct {
|
||||
svc *HistorySrv
|
||||
}
|
||||
|
||||
func NewStateHistoryApi(svc *HistorySrv) *HistoryApiHandler {
|
||||
return &HistoryApiHandler{
|
||||
svc: svc,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *HistoryApiHandler) handleRouteGetStateHistory(ctx *contextmodel.ReqContext) response.Response {
|
||||
return f.svc.RouteQueryStateHistory(ctx)
|
||||
}
|
@ -3931,7 +3931,6 @@
|
||||
"type": "object"
|
||||
},
|
||||
"receiver": {
|
||||
"description": "Receiver receiver",
|
||||
"properties": {
|
||||
"active": {
|
||||
"description": "active",
|
||||
@ -4885,4 +4884,4 @@
|
||||
}
|
||||
},
|
||||
"swagger": "2.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package definitions
|
||||
|
||||
import "github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
// swagger:route GET /api/v1/rules/history history RouteGetStateHistory
|
||||
//
|
||||
// Query state history.
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
// 200: StateHistory
|
||||
|
||||
type StateHistory struct {
|
||||
Results *data.Frame `json:"results"`
|
||||
}
|
@ -6642,6 +6642,23 @@
|
||||
"testing"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/rules/history": {
|
||||
"get": {
|
||||
"operationId": "RouteGetStateHistory",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/StateHistory"
|
||||
}
|
||||
},
|
||||
"summary": "Query state history.",
|
||||
"tags": [
|
||||
"history"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"produces": [
|
||||
|
@ -2632,6 +2632,23 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/rules/history": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"history"
|
||||
],
|
||||
"summary": "Query state history.",
|
||||
"operationId": "RouteGetStateHistory",
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/StateHistory"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
@ -6330,6 +6347,7 @@
|
||||
"$ref": "#/definitions/gettableAlert"
|
||||
},
|
||||
"gettableAlerts": {
|
||||
"description": "GettableAlerts gettable alerts",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableAlert"
|
||||
@ -6708,4 +6726,4 @@
|
||||
"type": "basic"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,17 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
// HistoryQuery represents a query for alert state history.
|
||||
type HistoryQuery struct {
|
||||
RuleUID string
|
||||
OrgID int64
|
||||
Labels map[string]string
|
||||
From time.Time
|
||||
To time.Time
|
||||
RuleUID string
|
||||
OrgID int64
|
||||
Labels map[string]string
|
||||
From time.Time
|
||||
To time.Time
|
||||
SignedInUser *user.SignedInUser
|
||||
}
|
||||
|
@ -268,6 +268,7 @@ func (ng *AlertNG) init() error {
|
||||
EvaluatorFactory: evalFactory,
|
||||
FeatureManager: ng.FeatureToggles,
|
||||
AppUrl: appUrl,
|
||||
Historian: history,
|
||||
}
|
||||
api.RegisterAPIEndpoints(ng.Metrics.GetAPIMetrics())
|
||||
|
||||
@ -383,7 +384,12 @@ func readQuotaConfig(cfg *setting.Cfg) (*quota.Map, error) {
|
||||
return limits, nil
|
||||
}
|
||||
|
||||
func configureHistorianBackend(ctx context.Context, cfg setting.UnifiedAlertingStateHistorySettings, ar annotations.Repository, ds dashboards.DashboardService, rs historian.RuleStore) (state.Historian, error) {
|
||||
type Historian interface {
|
||||
api.Historian
|
||||
state.Historian
|
||||
}
|
||||
|
||||
func configureHistorianBackend(ctx context.Context, cfg setting.UnifiedAlertingStateHistorySettings, ar annotations.Repository, ds dashboards.DashboardService, rs historian.RuleStore) (Historian, error) {
|
||||
if !cfg.Enabled {
|
||||
return historian.NewNopHistorian(), nil
|
||||
}
|
||||
|
@ -79,10 +79,11 @@ func (h *AnnotationBackend) QueryStates(ctx context.Context, query ngmodels.Hist
|
||||
}
|
||||
|
||||
q := annotations.ItemQuery{
|
||||
AlertId: rq.Result.ID,
|
||||
OrgId: query.OrgID,
|
||||
From: query.From.Unix(),
|
||||
To: query.To.Unix(),
|
||||
AlertId: rq.Result.ID,
|
||||
OrgId: query.OrgID,
|
||||
From: query.From.Unix(),
|
||||
To: query.To.Unix(),
|
||||
SignedInUser: query.SignedInUser,
|
||||
}
|
||||
items, err := h.annotations.Find(ctx, &q)
|
||||
if err != nil {
|
||||
|
@ -3,6 +3,8 @@ package historian
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/state"
|
||||
history_model "github.com/grafana/grafana/pkg/services/ngalert/state/historian/model"
|
||||
)
|
||||
@ -19,3 +21,7 @@ func (f *NoOpHistorian) RecordStatesAsync(ctx context.Context, _ history_model.R
|
||||
close(errCh)
|
||||
return errCh
|
||||
}
|
||||
|
||||
func (f *NoOpHistorian) QueryStates(ctx context.Context, query models.HistoryQuery) (*data.Frame, error) {
|
||||
return data.NewFrame("states"), nil
|
||||
}
|
||||
|
@ -19076,6 +19076,7 @@
|
||||
}
|
||||
},
|
||||
"gettableAlerts": {
|
||||
"description": "GettableAlerts gettable alerts",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/gettableAlert"
|
||||
|
Loading…
Reference in New Issue
Block a user