Remove redundant queries in GetAlertRules and GetOrgAlertRules and replace with ListAlertRules (#48108)

This commit is contained in:
George Robinson 2022-04-25 11:42:42 +01:00 committed by GitHub
parent 7cfab77650
commit c5547123bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 103 additions and 117 deletions

View File

@ -147,7 +147,7 @@ func (srv PrometheusSrv) RouteGetRuleStatuses(c *models.ReqContext) response.Res
DashboardUID: dashboardUID,
PanelID: panelID,
}
if err := srv.store.GetOrgAlertRules(c.Req.Context(), &alertRuleQuery); err != nil {
if err := srv.store.ListAlertRules(c.Req.Context(), &alertRuleQuery); err != nil {
ruleResponse.DiscoveryBase.Status = "error"
ruleResponse.DiscoveryBase.Error = fmt.Sprintf("failure getting rules: %s", err.Error())
ruleResponse.DiscoveryBase.ErrorType = apiv1.ErrServer

View File

@ -55,9 +55,9 @@ func (srv RulerSrv) RouteDeleteAlertRules(c *models.ReqContext) response.Respons
"namespace",
namespace.Title,
}
var ruleGroup *string
var ruleGroup string
if group, ok := web.Params(c.Req)[":Groupname"]; ok {
ruleGroup = &group
ruleGroup = group
loggerCtx = append(loggerCtx, "group", group)
}
logger := srv.log.New(loggerCtx...)
@ -68,12 +68,12 @@ func (srv RulerSrv) RouteDeleteAlertRules(c *models.ReqContext) response.Respons
var canDelete, cannotDelete []string
err = srv.xactManager.InTransaction(c.Req.Context(), func(ctx context.Context) error {
q := ngmodels.GetAlertRulesQuery{
OrgID: c.SignedInUser.OrgId,
NamespaceUID: namespace.Uid,
RuleGroup: ruleGroup,
q := ngmodels.ListAlertRulesQuery{
OrgID: c.SignedInUser.OrgId,
NamespaceUIDs: []string{namespace.Uid},
RuleGroup: ruleGroup,
}
if err = srv.store.GetAlertRules(ctx, &q); err != nil {
if err = srv.store.ListAlertRules(ctx, &q); err != nil {
return err
}
@ -128,11 +128,11 @@ func (srv RulerSrv) RouteGetNamespaceRulesConfig(c *models.ReqContext) response.
return toNamespaceErrorResponse(err)
}
q := ngmodels.GetAlertRulesQuery{
OrgID: c.SignedInUser.OrgId,
NamespaceUID: namespace.Uid,
q := ngmodels.ListAlertRulesQuery{
OrgID: c.SignedInUser.OrgId,
NamespaceUIDs: []string{namespace.Uid},
}
if err := srv.store.GetAlertRules(c.Req.Context(), &q); err != nil {
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to update rule group")
}
@ -178,12 +178,12 @@ func (srv RulerSrv) RouteGetRulegGroupConfig(c *models.ReqContext) response.Resp
}
ruleGroup := web.Params(c.Req)[":Groupname"]
q := ngmodels.GetAlertRulesQuery{
OrgID: c.SignedInUser.OrgId,
NamespaceUID: namespace.Uid,
RuleGroup: &ruleGroup,
q := ngmodels.ListAlertRulesQuery{
OrgID: c.SignedInUser.OrgId,
NamespaceUIDs: []string{namespace.Uid},
RuleGroup: ruleGroup,
}
if err := srv.store.GetAlertRules(c.Req.Context(), &q); err != nil {
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to get group alert rules")
}
@ -245,7 +245,7 @@ func (srv RulerSrv) RouteGetRulesConfig(c *models.ReqContext) response.Response
PanelID: panelID,
}
if err := srv.store.GetOrgAlertRules(c.Req.Context(), &q); err != nil {
if err := srv.store.ListAlertRules(c.Req.Context(), &q); err != nil {
return ErrResp(http.StatusInternalServerError, err, "failed to get alert rules")
}
@ -493,12 +493,12 @@ func (c *changes) isEmpty() bool {
// calculateChanges calculates the difference between rules in the group in the database and the submitted rules. If a submitted rule has UID it tries to find it in the database (in other groups).
// returns a list of rules that need to be added, updated and deleted. Deleted considered rules in the database that belong to the group but do not exist in the list of submitted rules.
func calculateChanges(ctx context.Context, ruleStore store.RuleStore, orgId int64, namespace *models.Folder, ruleGroupName string, submittedRules []*ngmodels.AlertRule) (*changes, error) {
q := &ngmodels.GetAlertRulesQuery{
OrgID: orgId,
NamespaceUID: namespace.Uid,
RuleGroup: &ruleGroupName,
q := &ngmodels.ListAlertRulesQuery{
OrgID: orgId,
NamespaceUIDs: []string{namespace.Uid},
RuleGroup: ruleGroupName,
}
if err := ruleStore.GetAlertRules(ctx, q); err != nil {
if err := ruleStore.ListAlertRules(ctx, q); err != nil {
return nil, fmt.Errorf("failed to query database for rules in the group %s: %w", ruleGroupName, err)
}
existingGroupRules := q.Result

View File

@ -232,7 +232,7 @@ func TestCalculateChanges(t *testing.T) {
expectedErr := errors.New("TEST ERROR")
fakeStore.Hook = func(cmd interface{}) error {
switch cmd.(type) {
case models.GetAlertRulesQuery:
case models.ListAlertRulesQuery:
return expectedErr
}
return nil

View File

@ -232,6 +232,7 @@ type ListAlertRulesQuery struct {
OrgID int64
NamespaceUIDs []string
ExcludeOrgs []int64
RuleGroup string
// DashboardUID and PanelID are optional and allow filtering rules
// to return just those for a dashboard and panel.
@ -250,21 +251,6 @@ type ListNamespaceAlertRulesQuery struct {
Result []*AlertRule
}
// GetAlertRulesQuery is the query for listing rule group alert rules
type GetAlertRulesQuery struct {
OrgID int64
// Namespace is the folder slug
NamespaceUID string
RuleGroup *string
// DashboardUID and PanelID are optional and allow filtering rules
// to return just those for a dashboard and panel.
DashboardUID string
PanelID int64
Result []*AlertRule
}
// ListRuleGroupsQuery is the query for listing unique rule groups
// across all organizations
type ListRuleGroupsQuery struct {

View File

@ -76,7 +76,7 @@ func (st *Manager) Warm(ctx context.Context) {
ruleCmd := ngModels.ListAlertRulesQuery{
OrgID: orgId,
}
if err := st.ruleStore.GetOrgAlertRules(ctx, &ruleCmd); err != nil {
if err := st.ruleStore.ListAlertRules(ctx, &ruleCmd); err != nil {
st.log.Error("unable to fetch previous state", "msg", err.Error())
}

View File

@ -38,10 +38,9 @@ type RuleStore interface {
DeleteAlertInstancesByRuleUID(ctx context.Context, orgID int64, ruleUID string) error
GetAlertRuleByUID(ctx context.Context, query *ngmodels.GetAlertRuleByUIDQuery) error
GetAlertRulesForScheduling(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
GetOrgAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error
// GetRuleGroups returns the unique rule groups across all organizations.
GetRuleGroups(ctx context.Context, query *ngmodels.ListRuleGroupsQuery) error
GetAlertRules(ctx context.Context, query *ngmodels.GetAlertRulesQuery) error
GetUserVisibleNamespaces(context.Context, int64, *models.SignedInUser) (map[string]*models.Folder, error)
GetNamespaceByTitle(context.Context, string, int64, *models.SignedInUser, bool) (*models.Folder, error)
InsertAlertRules(ctx context.Context, rule []ngmodels.AlertRule) error
@ -228,33 +227,39 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, rules []UpdateRule) erro
}
// GetOrgAlertRules is a handler for retrieving alert rules of specific organisation.
func (st DBstore) GetOrgAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error {
func (st DBstore) ListAlertRules(ctx context.Context, query *ngmodels.ListAlertRulesQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
alertRules := make([]*ngmodels.AlertRule, 0)
q := "SELECT * FROM alert_rule WHERE org_id = ?"
params := []interface{}{query.OrgID}
q := sess.Table("alert_rule")
if len(query.NamespaceUIDs) > 0 {
placeholders := make([]string, 0, len(query.NamespaceUIDs))
for _, folderUID := range query.NamespaceUIDs {
params = append(params, folderUID)
placeholders = append(placeholders, "?")
}
q = fmt.Sprintf("%s AND namespace_uid IN (%s)", q, strings.Join(placeholders, ","))
if query.OrgID >= 0 {
q = q.Where("org_id = ?", query.OrgID)
}
if query.DashboardUID != "" {
params = append(params, query.DashboardUID)
q = fmt.Sprintf("%s AND dashboard_uid = ?", q)
q = q.Where("dashboard_uid = ?", query.DashboardUID)
if query.PanelID != 0 {
params = append(params, query.PanelID)
q = fmt.Sprintf("%s AND panel_id = ?", q)
q = q.Where("panel_id = ?", query.PanelID)
}
}
q = fmt.Sprintf("%s ORDER BY id ASC", q)
if len(query.NamespaceUIDs) > 0 {
args := make([]interface{}, 0, len(query.NamespaceUIDs))
in := make([]string, 0, len(query.NamespaceUIDs))
for _, namespaceUID := range query.NamespaceUIDs {
args = append(args, namespaceUID)
in = append(in, "?")
}
q = q.Where(fmt.Sprintf("namespace_uid IN (%s)", strings.Join(in, ",")), args...)
}
if err := sess.SQL(q, params...).Find(&alertRules); err != nil {
if query.RuleGroup != "" {
q = q.Where("rule_group = ?", query.RuleGroup)
}
q = q.OrderBy("id ASC")
alertRules := make([]*ngmodels.AlertRule, 0)
if err := q.Find(&alertRules); err != nil {
return err
}
@ -274,30 +279,6 @@ func (st DBstore) GetRuleGroups(ctx context.Context, query *ngmodels.ListRuleGro
})
}
// GetAlertRules is a handler for retrieving rule group alert rules of specific organisation.
func (st DBstore) GetAlertRules(ctx context.Context, query *ngmodels.GetAlertRulesQuery) error {
return st.SQLStore.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
q := sess.Table("alert_rule").Where("org_id = ? AND namespace_uid = ?", query.OrgID, query.NamespaceUID)
if query.RuleGroup != nil {
q = q.Where("rule_group = ?", *query.RuleGroup)
}
if query.DashboardUID != "" {
q = q.Where("dashboard_uid = ?", query.DashboardUID)
if query.PanelID != 0 {
q = q.Where("panel_id = ?", query.PanelID)
}
}
alertRules := make([]*ngmodels.AlertRule, 0)
if err := q.Find(&alertRules); err != nil {
return err
}
query.Result = alertRules
return nil
})
}
// GetNamespaces returns the folders that are visible to the user and have at least one alert in it
func (st DBstore) GetUserVisibleNamespaces(ctx context.Context, orgID int64, user *models.SignedInUser) (map[string]*models.Folder, error) {
namespaceMap := make(map[string]*models.Folder)

View File

@ -166,16 +166,58 @@ func (f *FakeRuleStore) GetAlertRulesForScheduling(_ context.Context, q *models.
return nil
}
func (f *FakeRuleStore) GetOrgAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error {
func (f *FakeRuleStore) ListAlertRules(_ context.Context, q *models.ListAlertRulesQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.RecordedOps = append(f.RecordedOps, *q)
rules, ok := f.Rules[q.OrgID]
if !ok {
return nil
if err := f.Hook(*q); err != nil {
return err
}
q.Result = rules
hasDashboard := func(r *models.AlertRule, dashboardUID string, panelID int64) bool {
if dashboardUID != "" {
if r.DashboardUID == nil || *r.DashboardUID != dashboardUID {
return false
}
if panelID > 0 {
if r.PanelID == nil || *r.PanelID != panelID {
return false
}
}
}
return true
}
hasNamespace := func(r *models.AlertRule, namespaceUIDs []string) bool {
if len(namespaceUIDs) > 0 {
var ok bool
for _, uid := range q.NamespaceUIDs {
if uid == r.NamespaceUID {
ok = true
break
}
}
if !ok {
return false
}
}
return true
}
for _, r := range f.Rules[q.OrgID] {
if !hasDashboard(r, q.DashboardUID, q.PanelID) {
continue
}
if !hasNamespace(r, q.NamespaceUIDs) {
continue
}
if q.RuleGroup != "" && r.RuleGroup != q.RuleGroup {
continue
}
q.Result = append(q.Result, r)
}
return nil
}
@ -198,30 +240,6 @@ func (f *FakeRuleStore) GetRuleGroups(_ context.Context, q *models.ListRuleGroup
return nil
}
func (f *FakeRuleStore) GetAlertRules(_ context.Context, q *models.GetAlertRulesQuery) error {
f.mtx.Lock()
defer f.mtx.Unlock()
f.RecordedOps = append(f.RecordedOps, *q)
if err := f.Hook(*q); err != nil {
return err
}
rules, ok := f.Rules[q.OrgID]
if !ok {
return nil
}
var result []*models.AlertRule
for _, rule := range rules {
if q.NamespaceUID != rule.NamespaceUID {
continue
}
if q.RuleGroup != nil && *q.RuleGroup != rule.RuleGroup {
continue
}
result = append(result, rule)
}
q.Result = result
return nil
}
func (f *FakeRuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64, _ *models2.SignedInUser) (map[string]*models2.Folder, error) {
f.mtx.Lock()
defer f.mtx.Unlock()
@ -238,6 +256,7 @@ func (f *FakeRuleStore) GetUserVisibleNamespaces(_ context.Context, orgID int64,
}
return namespacesMap, nil
}
func (f *FakeRuleStore) GetNamespaceByTitle(_ context.Context, title string, orgID int64, _ *models2.SignedInUser, _ bool) (*models2.Folder, error) {
folders := f.Folders[orgID]
for _, folder := range folders {

View File

@ -113,12 +113,12 @@ func CreateTestAlertRuleWithLabels(t *testing.T, ctx context.Context, dbstore *s
})
require.NoError(t, err)
q := models.GetAlertRulesQuery{
OrgID: orgID,
NamespaceUID: "namespace",
RuleGroup: &ruleGroup,
q := models.ListAlertRulesQuery{
OrgID: orgID,
NamespaceUIDs: []string{"namespace"},
RuleGroup: ruleGroup,
}
err = dbstore.GetAlertRules(ctx, &q)
err = dbstore.ListAlertRules(ctx, &q)
require.NoError(t, err)
require.NotEmpty(t, q.Result)