mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Refactor api_prometheus.go request handlers. (#86639)
This splits the request handlers into two functions, one which is the actual handler and one which is independent from the Grafana `ReqContext` object. This is to make it easier to reuse the implementation in other code. Part of the refactoring changes the functions which get query parameters from the request to operate on a `url.Values` instead of the request object. The change also makes the code consistently use `req.Form` instead of a combination of `req.URL.Query()` and `req.Form`, though I have left `api_ruler` as-is to avoid this PR growing too large.
This commit is contained in:
parent
68564b1940
commit
a6ad2380bf
@ -1,10 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/api/response"
|
"github.com/grafana/grafana/pkg/api/response"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||||
"github.com/grafana/grafana/pkg/services/folder"
|
|
||||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||||
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
"github.com/grafana/grafana/pkg/services/ngalert/eval"
|
||||||
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
|
||||||
@ -61,6 +60,20 @@ func (srv PrometheusSrv) RouteGetAlertStatuses(c *contextmodel.ReqContext) respo
|
|||||||
// As we are using req.Form directly, this triggers a call to ParseForm() if needed.
|
// As we are using req.Form directly, this triggers a call to ParseForm() if needed.
|
||||||
c.Query("")
|
c.Query("")
|
||||||
|
|
||||||
|
resp := PrepareAlertStatuses(srv.manager, AlertStatusesOptions{
|
||||||
|
OrgID: c.SignedInUser.GetOrgID(),
|
||||||
|
Query: c.Req.Form,
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.JSON(resp.HTTPStatusCode(), resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlertStatusesOptions struct {
|
||||||
|
OrgID int64
|
||||||
|
Query url.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrepareAlertStatuses(manager state.AlertInstanceManager, opts AlertStatusesOptions) apimodels.AlertResponse {
|
||||||
alertResponse := apimodels.AlertResponse{
|
alertResponse := apimodels.AlertResponse{
|
||||||
DiscoveryBase: apimodels.DiscoveryBase{
|
DiscoveryBase: apimodels.DiscoveryBase{
|
||||||
Status: "success",
|
Status: "success",
|
||||||
@ -71,11 +84,11 @@ func (srv PrometheusSrv) RouteGetAlertStatuses(c *contextmodel.ReqContext) respo
|
|||||||
}
|
}
|
||||||
|
|
||||||
var labelOptions []ngmodels.LabelOption
|
var labelOptions []ngmodels.LabelOption
|
||||||
if !getBoolWithDefault(c.Req.Form, queryIncludeInternalLabels, false) {
|
if !getBoolWithDefault(opts.Query, queryIncludeInternalLabels, false) {
|
||||||
labelOptions = append(labelOptions, ngmodels.WithoutInternalLabels())
|
labelOptions = append(labelOptions, ngmodels.WithoutInternalLabels())
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, alertState := range srv.manager.GetAll(c.SignedInUser.GetOrgID()) {
|
for _, alertState := range manager.GetAll(opts.OrgID) {
|
||||||
startsAt := alertState.StartsAt
|
startsAt := alertState.StartsAt
|
||||||
valString := ""
|
valString := ""
|
||||||
|
|
||||||
@ -95,7 +108,7 @@ func (srv PrometheusSrv) RouteGetAlertStatuses(c *contextmodel.ReqContext) respo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.JSON(alertResponse.HTTPStatusCode(), alertResponse)
|
return alertResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatValues(alertState *state.State) string {
|
func formatValues(alertState *state.State) string {
|
||||||
@ -126,16 +139,16 @@ func formatValues(alertState *state.State) string {
|
|||||||
return fv
|
return fv
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPanelIDFromRequest(r *http.Request) (int64, error) {
|
func getPanelIDFromQuery(v url.Values) (int64, error) {
|
||||||
if s := strings.TrimSpace(r.URL.Query().Get("panel_id")); s != "" {
|
if s := strings.TrimSpace(v.Get("panel_id")); s != "" {
|
||||||
return strconv.ParseInt(s, 10, 64)
|
return strconv.ParseInt(s, 10, 64)
|
||||||
}
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMatchersFromRequest(r *http.Request) (labels.Matchers, error) {
|
func getMatchersFromQuery(v url.Values) (labels.Matchers, error) {
|
||||||
var matchers labels.Matchers
|
var matchers labels.Matchers
|
||||||
for _, s := range r.URL.Query()["matcher"] {
|
for _, s := range v["matcher"] {
|
||||||
var m labels.Matcher
|
var m labels.Matcher
|
||||||
if err := json.Unmarshal([]byte(s), &m); err != nil {
|
if err := json.Unmarshal([]byte(s), &m); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -148,9 +161,9 @@ func getMatchersFromRequest(r *http.Request) (labels.Matchers, error) {
|
|||||||
return matchers, nil
|
return matchers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatesFromRequest(r *http.Request) ([]eval.State, error) {
|
func getStatesFromQuery(v url.Values) ([]eval.State, error) {
|
||||||
var states []eval.State
|
var states []eval.State
|
||||||
for _, s := range r.URL.Query()["state"] {
|
for _, s := range v["state"] {
|
||||||
s = strings.ToLower(s)
|
s = strings.ToLower(s)
|
||||||
switch s {
|
switch s {
|
||||||
case "normal", "inactive":
|
case "normal", "inactive":
|
||||||
@ -171,6 +184,18 @@ func getStatesFromRequest(r *http.Request) ([]eval.State, error) {
|
|||||||
return states, nil
|
return states, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RuleGroupStatusesOptions struct {
|
||||||
|
Ctx context.Context
|
||||||
|
OrgID int64
|
||||||
|
Query url.Values
|
||||||
|
Namespaces map[string]string
|
||||||
|
AuthorizeRuleGroup func(rules []*ngmodels.AlertRule) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListAlertRulesStore interface {
|
||||||
|
ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) (ngmodels.RulesGroup, error)
|
||||||
|
}
|
||||||
|
|
||||||
func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) response.Response {
|
func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) response.Response {
|
||||||
// As we are using req.Form directly, this triggers a call to ParseForm() if needed.
|
// As we are using req.Form directly, this triggers a call to ParseForm() if needed.
|
||||||
c.Query("")
|
c.Query("")
|
||||||
@ -184,48 +209,6 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) respon
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboardUID := c.Query("dashboard_uid")
|
|
||||||
panelID, err := getPanelIDFromRequest(c.Req)
|
|
||||||
if err != nil {
|
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
|
||||||
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("invalid panel_id: %s", err.Error())
|
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
|
||||||
}
|
|
||||||
if dashboardUID == "" && panelID != 0 {
|
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
|
||||||
ruleResponse.DiscoveryBase.Error = "panel_id must be set with dashboard_uid"
|
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
|
||||||
}
|
|
||||||
|
|
||||||
limitGroups := getInt64WithDefault(c.Req.Form, "limit", -1)
|
|
||||||
limitRulesPerGroup := getInt64WithDefault(c.Req.Form, "limit_rules", -1)
|
|
||||||
limitAlertsPerRule := getInt64WithDefault(c.Req.Form, "limit_alerts", -1)
|
|
||||||
matchers, err := getMatchersFromRequest(c.Req)
|
|
||||||
if err != nil {
|
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
|
||||||
ruleResponse.DiscoveryBase.Error = err.Error()
|
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
|
||||||
}
|
|
||||||
withStates, err := getStatesFromRequest(c.Req)
|
|
||||||
if err != nil {
|
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
|
||||||
ruleResponse.DiscoveryBase.Error = err.Error()
|
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
|
||||||
}
|
|
||||||
withStatesFast := make(map[eval.State]struct{})
|
|
||||||
for _, state := range withStates {
|
|
||||||
withStatesFast[state] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var labelOptions []ngmodels.LabelOption
|
|
||||||
if !getBoolWithDefault(c.Req.Form, queryIncludeInternalLabels, false) {
|
|
||||||
labelOptions = append(labelOptions, ngmodels.WithoutInternalLabels())
|
|
||||||
}
|
|
||||||
|
|
||||||
namespaceMap, err := srv.store.GetUserVisibleNamespaces(c.Req.Context(), c.SignedInUser.GetOrgID(), c.SignedInUser)
|
namespaceMap, err := srv.store.GetUserVisibleNamespaces(c.Req.Context(), c.SignedInUser.GetOrgID(), c.SignedInUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
@ -234,28 +217,98 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) respon
|
|||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(namespaceMap) == 0 {
|
namespaces := map[string]string{}
|
||||||
srv.log.Debug("User does not have access to any namespaces")
|
for namespaceUID, folder := range namespaceMap {
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
namespaces[namespaceUID] = folder.Fullpath
|
||||||
}
|
}
|
||||||
|
|
||||||
namespaceUIDs := make([]string, len(namespaceMap))
|
ruleResponse = PrepareRuleGroupStatuses(srv.log, srv.manager, srv.store, RuleGroupStatusesOptions{
|
||||||
for k := range namespaceMap {
|
Ctx: c.Req.Context(),
|
||||||
|
OrgID: c.OrgID,
|
||||||
|
Query: c.Req.Form,
|
||||||
|
Namespaces: namespaces,
|
||||||
|
AuthorizeRuleGroup: func(rules []*ngmodels.AlertRule) (bool, error) {
|
||||||
|
return srv.authz.HasAccessToRuleGroup(c.Req.Context(), c.SignedInUser, rules)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrepareRuleGroupStatuses(log log.Logger, manager state.AlertInstanceManager, store ListAlertRulesStore, opts RuleGroupStatusesOptions) apimodels.RuleResponse {
|
||||||
|
ruleResponse := apimodels.RuleResponse{
|
||||||
|
DiscoveryBase: apimodels.DiscoveryBase{
|
||||||
|
Status: "success",
|
||||||
|
},
|
||||||
|
Data: apimodels.RuleDiscovery{
|
||||||
|
RuleGroups: []apimodels.RuleGroup{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardUID := opts.Query.Get("dashboard_uid")
|
||||||
|
panelID, err := getPanelIDFromQuery(opts.Query)
|
||||||
|
if err != nil {
|
||||||
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("invalid panel_id: %s", err.Error())
|
||||||
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
||||||
|
return ruleResponse
|
||||||
|
}
|
||||||
|
if dashboardUID == "" && panelID != 0 {
|
||||||
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
|
ruleResponse.DiscoveryBase.Error = "panel_id must be set with dashboard_uid"
|
||||||
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
||||||
|
return ruleResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
limitGroups := getInt64WithDefault(opts.Query, "limit", -1)
|
||||||
|
limitRulesPerGroup := getInt64WithDefault(opts.Query, "limit_rules", -1)
|
||||||
|
limitAlertsPerRule := getInt64WithDefault(opts.Query, "limit_alerts", -1)
|
||||||
|
matchers, err := getMatchersFromQuery(opts.Query)
|
||||||
|
if err != nil {
|
||||||
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
|
ruleResponse.DiscoveryBase.Error = err.Error()
|
||||||
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
||||||
|
return ruleResponse
|
||||||
|
}
|
||||||
|
withStates, err := getStatesFromQuery(opts.Query)
|
||||||
|
if err != nil {
|
||||||
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
|
ruleResponse.DiscoveryBase.Error = err.Error()
|
||||||
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrBadData
|
||||||
|
return ruleResponse
|
||||||
|
}
|
||||||
|
withStatesFast := make(map[eval.State]struct{})
|
||||||
|
for _, state := range withStates {
|
||||||
|
withStatesFast[state] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var labelOptions []ngmodels.LabelOption
|
||||||
|
if !getBoolWithDefault(opts.Query, queryIncludeInternalLabels, false) {
|
||||||
|
labelOptions = append(labelOptions, ngmodels.WithoutInternalLabels())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts.Namespaces) == 0 {
|
||||||
|
log.Debug("User does not have access to any namespaces")
|
||||||
|
return ruleResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaceUIDs := make([]string, len(opts.Namespaces))
|
||||||
|
for k := range opts.Namespaces {
|
||||||
namespaceUIDs = append(namespaceUIDs, k)
|
namespaceUIDs = append(namespaceUIDs, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
alertRuleQuery := ngmodels.ListAlertRulesQuery{
|
alertRuleQuery := ngmodels.ListAlertRulesQuery{
|
||||||
OrgID: c.SignedInUser.GetOrgID(),
|
OrgID: opts.OrgID,
|
||||||
NamespaceUIDs: namespaceUIDs,
|
NamespaceUIDs: namespaceUIDs,
|
||||||
DashboardUID: dashboardUID,
|
DashboardUID: dashboardUID,
|
||||||
PanelID: panelID,
|
PanelID: panelID,
|
||||||
}
|
}
|
||||||
ruleList, err := srv.store.ListAlertRules(c.Req.Context(), &alertRuleQuery)
|
ruleList, err := store.ListAlertRules(opts.Ctx, &alertRuleQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
return ruleResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group rules together by Namespace and Rule Group. Rules are also grouped by Org ID,
|
// Group rules together by Namespace and Rule Group. Rules are also grouped by Org ID,
|
||||||
@ -275,22 +328,22 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) respon
|
|||||||
|
|
||||||
rulesTotals := make(map[string]int64, len(groupedRules))
|
rulesTotals := make(map[string]int64, len(groupedRules))
|
||||||
for groupKey, rules := range groupedRules {
|
for groupKey, rules := range groupedRules {
|
||||||
folder := namespaceMap[groupKey.NamespaceUID]
|
folder, ok := opts.Namespaces[groupKey.NamespaceUID]
|
||||||
if folder == nil {
|
if !ok {
|
||||||
srv.log.Warn("Query returned rules that belong to folder the user does not have access to. All rules that belong to that namespace will not be added to the response", "folder_uid", groupKey.NamespaceUID)
|
log.Warn("Query returned rules that belong to folder the user does not have access to. All rules that belong to that namespace will not be added to the response", "folder_uid", groupKey.NamespaceUID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ok, err := srv.authz.HasAccessToRuleGroup(c.Req.Context(), c.SignedInUser, rules)
|
ok, err := opts.AuthorizeRuleGroup(rules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ruleResponse.DiscoveryBase.Status = "error"
|
ruleResponse.DiscoveryBase.Status = "error"
|
||||||
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("cannot authorize access to rule group: %s", err.Error())
|
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("cannot authorize access to rule group: %s", err.Error())
|
||||||
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
return ruleResponse
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ruleGroup, totals := srv.toRuleGroup(groupKey, folder, rules, limitAlertsPerRule, withStatesFast, matchers, labelOptions)
|
ruleGroup, totals := toRuleGroup(log, manager, groupKey, folder, rules, limitAlertsPerRule, withStatesFast, matchers, labelOptions)
|
||||||
ruleGroup.Totals = totals
|
ruleGroup.Totals = totals
|
||||||
for k, v := range totals {
|
for k, v := range totals {
|
||||||
rulesTotals[k] += v
|
rulesTotals[k] += v
|
||||||
@ -335,7 +388,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *contextmodel.ReqContext) respon
|
|||||||
ruleResponse.Data.RuleGroups = ruleResponse.Data.RuleGroups[0:limitGroups]
|
ruleResponse.Data.RuleGroups = ruleResponse.Data.RuleGroups[0:limitGroups]
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.JSON(ruleResponse.HTTPStatusCode(), ruleResponse)
|
return ruleResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the same as matchers.Matches but avoids the need to create a LabelSet
|
// This is the same as matchers.Matches but avoids the need to create a LabelSet
|
||||||
@ -348,11 +401,11 @@ func matchersMatch(matchers []*labels.Matcher, labels map[string]string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv PrometheusSrv) toRuleGroup(groupKey ngmodels.AlertRuleGroupKey, folder *folder.Folder, rules []*ngmodels.AlertRule, limitAlerts int64, withStates map[eval.State]struct{}, matchers labels.Matchers, labelOptions []ngmodels.LabelOption) (*apimodels.RuleGroup, map[string]int64) {
|
func toRuleGroup(log log.Logger, manager state.AlertInstanceManager, groupKey ngmodels.AlertRuleGroupKey, folderFullPath string, rules []*ngmodels.AlertRule, limitAlerts int64, withStates map[eval.State]struct{}, matchers labels.Matchers, labelOptions []ngmodels.LabelOption) (*apimodels.RuleGroup, map[string]int64) {
|
||||||
newGroup := &apimodels.RuleGroup{
|
newGroup := &apimodels.RuleGroup{
|
||||||
Name: groupKey.RuleGroup,
|
Name: groupKey.RuleGroup,
|
||||||
// file is what Prometheus uses for provisioning, we replace it with namespace which is the folder in Grafana.
|
// file is what Prometheus uses for provisioning, we replace it with namespace which is the folder in Grafana.
|
||||||
File: folder.Fullpath,
|
File: folderFullPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
rulesTotals := make(map[string]int64, len(rules))
|
rulesTotals := make(map[string]int64, len(rules))
|
||||||
@ -362,7 +415,7 @@ func (srv PrometheusSrv) toRuleGroup(groupKey ngmodels.AlertRuleGroupKey, folder
|
|||||||
alertingRule := apimodels.AlertingRule{
|
alertingRule := apimodels.AlertingRule{
|
||||||
State: "inactive",
|
State: "inactive",
|
||||||
Name: rule.Title,
|
Name: rule.Title,
|
||||||
Query: ruleToQuery(srv.log, rule),
|
Query: ruleToQuery(log, rule),
|
||||||
Duration: rule.For.Seconds(),
|
Duration: rule.For.Seconds(),
|
||||||
Annotations: rule.Annotations,
|
Annotations: rule.Annotations,
|
||||||
}
|
}
|
||||||
@ -375,7 +428,7 @@ func (srv PrometheusSrv) toRuleGroup(groupKey ngmodels.AlertRuleGroupKey, folder
|
|||||||
LastEvaluation: time.Time{},
|
LastEvaluation: time.Time{},
|
||||||
}
|
}
|
||||||
|
|
||||||
states := srv.manager.GetStatesForRuleUID(rule.OrgID, rule.UID)
|
states := manager.GetStatesForRuleUID(rule.OrgID, rule.UID)
|
||||||
totals := make(map[string]int64)
|
totals := make(map[string]int64)
|
||||||
totalsFiltered := make(map[string]int64)
|
totalsFiltered := make(map[string]int64)
|
||||||
for _, alertState := range states {
|
for _, alertState := range states {
|
||||||
|
@ -234,7 +234,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *contextmodel.ReqContext) response.Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
dashboardUID := c.Query("dashboard_uid")
|
dashboardUID := c.Query("dashboard_uid")
|
||||||
panelID, err := getPanelIDFromRequest(c.Req)
|
panelID, err := getPanelIDFromQuery(c.Req.URL.Query())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrResp(http.StatusBadRequest, err, "invalid panel_id")
|
return ErrResp(http.StatusBadRequest, err, "invalid panel_id")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user