Alerting: Tiny refactor on the eval and schedule packages (#66130)

* Alerting: Tiny refactor on the eval and schedule packages

two very small things:

- We had a constructor on something called a `Context` which is not a `context.Context` so let's just name that constructor `NewContext`
- The user that we use to run query evaluations is the same (with some variation) abstract it to a function so that it can be re-used when necessary.

* Update pkg/services/ngalert/schedule/schedule.go

Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>

* Update pkg/services/ngalert/schedule/schedule.go

Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>

---------

Co-authored-by: Alexander Weaver <weaver.alex.d@gmail.com>
This commit is contained in:
gotjosh 2023-04-06 16:02:28 +01:00 committed by GitHub
parent 3e85c90759
commit 1c3ce0735f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 32 additions and 24 deletions

View File

@ -303,7 +303,7 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *contextmodel.ReqContext, ruleGro
}
rules, err := validateRuleGroup(&ruleGroupConfig, c.SignedInUser.OrgID, namespace, func(condition ngmodels.Condition) error {
return srv.conditionValidator.Validate(eval.Context(c.Req.Context(), c.SignedInUser), condition)
return srv.conditionValidator.Validate(eval.NewContext(c.Req.Context(), c.SignedInUser), condition)
}, srv.cfg)
if err != nil {
return ErrResp(http.StatusBadRequest, err, "")

View File

@ -52,7 +52,7 @@ func (srv TestingApiSrv) RouteTestGrafanaRuleConfig(c *contextmodel.ReqContext,
Condition: body.GrafanaManagedCondition.Condition,
Data: queries,
}
ctx := eval.Context(c.Req.Context(), c.SignedInUser)
ctx := eval.NewContext(c.Req.Context(), c.SignedInUser)
conditionEval, err := srv.evaluator.Create(ctx, evalCond)
if err != nil {
@ -128,7 +128,7 @@ func (srv TestingApiSrv) RouteEvalQueries(c *contextmodel.ReqContext, cmd apimod
if len(cmd.Data) > 0 {
cond.Condition = cmd.Data[0].RefID
}
evaluator, err := srv.evaluator.Create(eval.Context(c.Req.Context(), c.SignedInUser), cond)
evaluator, err := srv.evaluator.Create(eval.NewContext(c.Req.Context(), c.SignedInUser), cond)
if err != nil {
return ErrResp(http.StatusBadRequest, err, "Failed to build evaluator for queries and expressions")

View File

@ -12,7 +12,7 @@ type EvaluationContext struct {
User *user.SignedInUser
}
func Context(ctx context.Context, user *user.SignedInUser) EvaluationContext {
func NewContext(ctx context.Context, user *user.SignedInUser) EvaluationContext {
return EvaluationContext{
Ctx: ctx,
User: user,

View File

@ -220,7 +220,7 @@ func (s State) String() string {
return [...]string{"Normal", "Alerting", "Pending", "NoData", "Error"}[s]
}
func buildDatasourceHeaders(ctx EvaluationContext) map[string]string {
func buildDatasourceHeaders(ctx context.Context) map[string]string {
headers := map[string]string{
// Many data sources check this in query method as sometimes alerting needs special considerations.
// Several existing systems also compare against the value of this header. Altering this constitutes a breaking change.
@ -233,7 +233,7 @@ func buildDatasourceHeaders(ctx EvaluationContext) map[string]string {
models.CacheSkipHeaderName: "true",
}
key, ok := models.RuleKeyFromContext(ctx.Ctx)
key, ok := models.RuleKeyFromContext(ctx)
if ok {
headers["X-Rule-Uid"] = key.UID
headers["X-Grafana-Org-Id"] = strconv.FormatInt(key.OrgID, 10)
@ -246,7 +246,7 @@ func buildDatasourceHeaders(ctx EvaluationContext) map[string]string {
func getExprRequest(ctx EvaluationContext, data []models.AlertQuery, dsCacheService datasources.CacheService) (*expr.Request, error) {
req := &expr.Request{
OrgId: ctx.User.OrgID,
Headers: buildDatasourceHeaders(ctx),
Headers: buildDatasourceHeaders(ctx.Ctx),
}
datasources := make(map[string]*datasources.DataSource, len(data))
@ -295,7 +295,8 @@ func getExprRequest(ctx EvaluationContext, data []models.AlertQuery, dsCacheServ
type NumberValueCapture struct {
Var string // RefID
Labels data.Labels
Value *float64
Value *float64
}
func queryDataResponseToExecutionResults(c models.Condition, execResp *backend.QueryDataResponse) ExecutionResults {

View File

@ -533,7 +533,7 @@ func TestValidate(t *testing.T) {
})
evaluator := NewEvaluatorFactory(setting.UnifiedAlertingSettings{}, cacheService, expr.ProvideService(&setting.Cfg{ExpressionsEnabled: true}, nil, nil), store)
evalCtx := Context(context.Background(), u)
evalCtx := NewContext(context.Background(), u)
err := evaluator.Validate(evalCtx, condition)
if testCase.error {

View File

@ -97,6 +97,10 @@ type AlertQuery struct {
modelProps map[string]interface{}
}
func (aq *AlertQuery) String() string {
return fmt.Sprintf("refID: %s, queryType: %s, datasourceUID: %s", aq.RefID, aq.QueryType, aq.DatasourceUID)
}
func (aq *AlertQuery) setModelProps() error {
aq.modelProps = make(map[string]interface{})
err := json.Unmarshal(aq.Model, &aq.modelProps)

View File

@ -373,21 +373,7 @@ func (sch *schedule) ruleRoutine(grafanaCtx context.Context, key ngmodels.AlertR
logger := logger.New("version", e.rule.Version, "attempt", attempt, "now", e.scheduledAt)
start := sch.clock.Now()
schedulerUser := &user.SignedInUser{
UserID: -1,
IsServiceAccount: true,
Login: "grafana_scheduler",
OrgID: e.rule.OrgID,
OrgRole: org.RoleAdmin,
Permissions: map[int64]map[string][]string{
e.rule.OrgID: {
datasources.ActionQuery: []string{
datasources.ScopeAll,
},
},
},
}
evalCtx := eval.Context(ctx, schedulerUser)
evalCtx := eval.NewContext(ctx, SchedulerUserFor(e.rule.OrgID))
ruleEval, err := sch.evaluatorFactory.Create(evalCtx, e.rule.GetEvalCondition())
var results eval.Results
var dur time.Duration
@ -580,3 +566,20 @@ func (sch *schedule) getRuleExtraLabels(evalCtx *evaluation) map[string]string {
}
return extraLabels
}
func SchedulerUserFor(orgID int64) *user.SignedInUser {
return &user.SignedInUser{
UserID: -1,
IsServiceAccount: true,
Login: "grafana_scheduler",
OrgID: orgID,
OrgRole: org.RoleAdmin,
Permissions: map[int64]map[string][]string{
orgID: {
datasources.ActionQuery: []string{
datasources.ScopeAll,
},
},
},
}
}