Alerting: Add traceability headers for alert queries (#57127)

* Define EvaluationContext

* Refactor ConditionEval to use new context struct

* Refactor QueriesAndExpressionsEval to use EvaluationContext

* Remove dead field from AlertExecCtx

* Refactor Validate to use EvaluationContext

* Get rid of privately used AlertExecCtx

* Move EvaluationContext to new file and add helper

* Add builder pattern and bind rule info to context

* Extract header logic and add rule UID header

* Fix missing call
This commit is contained in:
Alexander Weaver
2022-10-19 14:19:43 -05:00
committed by GitHub
parent 85cda0db69
commit 4eb8e4ff66
8 changed files with 153 additions and 109 deletions
+3 -3
View File
@@ -10,10 +10,10 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/ngalert/eval"
"github.com/grafana/grafana/pkg/services/ngalert/provisioning"
"github.com/grafana/grafana/pkg/services/ngalert/store"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/user"
"github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/common/model"
@@ -30,7 +30,7 @@ import (
type ConditionValidator interface {
// Validate validates that the condition is correct. Returns nil if the condition is correct. Otherwise, error that describes the failure
Validate(ctx context.Context, user *user.SignedInUser, condition ngmodels.Condition) error
Validate(ctx eval.EvaluationContext, condition ngmodels.Condition) error
}
type RulerSrv struct {
@@ -308,7 +308,7 @@ func (srv RulerSrv) RoutePostNameRulesConfig(c *models.ReqContext, ruleGroupConf
}
rules, err := validateRuleGroup(&ruleGroupConfig, c.SignedInUser.OrgID, namespace, func(condition ngmodels.Condition) error {
return srv.conditionValidator.Validate(c.Req.Context(), c.SignedInUser, condition)
return srv.conditionValidator.Validate(eval.Context(c.Req.Context(), c.SignedInUser), condition)
}, srv.cfg)
if err != nil {
return ErrResp(http.StatusBadRequest, err, "")
+12 -11
View File
@@ -42,17 +42,18 @@ func (srv TestingApiSrv) RouteTestGrafanaRuleConfig(c *models.ReqContext, body a
Condition: body.GrafanaManagedCondition.Condition,
Data: body.GrafanaManagedCondition.Data,
}
ctx := eval.Context(c.Req.Context(), c.SignedInUser)
if err := srv.evaluator.Validate(c.Req.Context(), c.SignedInUser, evalCond); err != nil {
if err := srv.evaluator.Validate(ctx, evalCond); err != nil {
return ErrResp(http.StatusBadRequest, err, "invalid condition")
}
now := body.GrafanaManagedCondition.Now
if now.IsZero() {
now = timeNow()
ctx = ctx.When(body.GrafanaManagedCondition.Now)
if ctx.At.IsZero() {
ctx = ctx.When(timeNow())
}
evalResults := srv.evaluator.ConditionEval(c.Req.Context(), c.SignedInUser, evalCond, now)
evalResults := srv.evaluator.ConditionEval(ctx, evalCond)
frame := evalResults.AsDataFrame()
return response.JSONStreaming(http.StatusOK, util.DynMap{
@@ -99,18 +100,18 @@ func (srv TestingApiSrv) RouteTestRuleConfig(c *models.ReqContext, body apimodel
}
func (srv TestingApiSrv) RouteEvalQueries(c *models.ReqContext, cmd apimodels.EvalQueriesPayload) response.Response {
now := cmd.Now
if now.IsZero() {
now = timeNow()
}
if !authorizeDatasourceAccessForRule(&ngmodels.AlertRule{Data: cmd.Data}, func(evaluator accesscontrol.Evaluator) bool {
return accesscontrol.HasAccess(srv.accessControl, c)(accesscontrol.ReqSignedIn, evaluator)
}) {
return ErrResp(http.StatusUnauthorized, fmt.Errorf("%w to query one or many data sources used by the rule", ErrAuthorization), "")
}
evalResults, err := srv.evaluator.QueriesAndExpressionsEval(c.Req.Context(), c.SignedInUser, cmd.Data, now)
ctx := eval.Context(c.Req.Context(), c.SignedInUser).When(cmd.Now)
if ctx.At.IsZero() {
ctx = ctx.When(timeNow())
}
evalResults, err := srv.evaluator.QueriesAndExpressionsEval(ctx, cmd.Data)
if err != nil {
return ErrResp(http.StatusBadRequest, err, "Failed to evaluate queries and expressions")
}
+6 -6
View File
@@ -70,8 +70,8 @@ func TestRouteTestGrafanaRuleConfig(t *testing.T) {
evaluator := &eval.FakeEvaluator{}
var result []eval.Result
evaluator.EXPECT().Validate(mock.Anything, mock.Anything, mock.Anything).Return(nil)
evaluator.EXPECT().ConditionEval(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(result)
evaluator.EXPECT().Validate(mock.Anything, mock.Anything).Return(nil)
evaluator.EXPECT().ConditionEval(mock.Anything, mock.Anything).Return(result)
srv := createTestingApiSrv(ds, ac, evaluator)
@@ -112,8 +112,8 @@ func TestRouteTestGrafanaRuleConfig(t *testing.T) {
evaluator := &eval.FakeEvaluator{}
var result []eval.Result
evaluator.EXPECT().Validate(mock.Anything, mock.Anything, mock.Anything).Return(nil)
evaluator.EXPECT().ConditionEval(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(result)
evaluator.EXPECT().Validate(mock.Anything, mock.Anything).Return(nil)
evaluator.EXPECT().ConditionEval(mock.Anything, mock.Anything).Return(result)
srv := createTestingApiSrv(ds, ac, evaluator)
@@ -203,7 +203,7 @@ func TestRouteEvalQueries(t *testing.T) {
},
},
}
evaluator.EXPECT().QueriesAndExpressionsEval(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(result, nil)
evaluator.EXPECT().QueriesAndExpressionsEval(mock.Anything, mock.Anything).Return(result, nil)
srv := createTestingApiSrv(ds, ac, evaluator)
@@ -246,7 +246,7 @@ func TestRouteEvalQueries(t *testing.T) {
},
},
}
evaluator.EXPECT().QueriesAndExpressionsEval(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(result, nil)
evaluator.EXPECT().QueriesAndExpressionsEval(mock.Anything, mock.Anything).Return(result, nil)
srv := createTestingApiSrv(ds, ac, evaluator)