Alerting: Move BaseInterval and MinInterval to UnifiedAlerting config (#45107)

* use base interval if legacy value is less than the base interval
This commit is contained in:
Yuriy Tseretyan
2022-02-11 16:13:49 -05:00
committed by GitHub
parent 4f815e3d8e
commit 095ea44e97
6 changed files with 145 additions and 137 deletions

View File

@@ -3,7 +3,6 @@ package ngalert
import (
"context"
"net/url"
"time"
"github.com/benbjohnson/clock"
"golang.org/x/sync/errgroup"
@@ -28,17 +27,6 @@ import (
"github.com/grafana/grafana/pkg/setting"
)
const (
// scheduler interval
// changing this value is discouraged
// because this could cause existing alert definition
// with intervals that are not exactly divided by this number
// not to be evaluated
defaultBaseIntervalSeconds = 10
// default alert definition interval
defaultIntervalSeconds int64 = 6 * defaultBaseIntervalSeconds
)
func ProvideService(cfg *setting.Cfg, dataSourceCache datasources.CacheService, routeRegister routing.RouteRegister,
sqlStore *sqlstore.SQLStore, kvStore kvstore.KVStore, expressionService *expr.Service, dataProxy *datasourceproxy.DataSourceProxyService,
quotaService *quota.QuotaService, secretsService secrets.Service, notificationService notifications.Service, m *metrics.NGAlert) (*AlertNG, error) {
@@ -92,15 +80,9 @@ type AlertNG struct {
func (ng *AlertNG) init() error {
var err error
baseInterval := ng.Cfg.AlertingBaseInterval
if baseInterval <= 0 {
baseInterval = defaultBaseIntervalSeconds
}
baseInterval *= time.Second
store := &store.DBstore{
BaseInterval: baseInterval,
DefaultInterval: ng.getRuleDefaultInterval(),
BaseInterval: ng.Cfg.UnifiedAlerting.BaseInterval,
DefaultInterval: ng.Cfg.UnifiedAlerting.DefaultAlertForDuration,
SQLStore: ng.SQLStore,
Logger: ng.Log,
}
@@ -119,7 +101,7 @@ func (ng *AlertNG) init() error {
schedCfg := schedule.SchedulerCfg{
C: clock.New(),
BaseInterval: baseInterval,
BaseInterval: ng.Cfg.UnifiedAlerting.BaseInterval,
Logger: ng.Log,
MaxAttempts: ng.Cfg.UnifiedAlerting.MaxAttempts,
Evaluator: eval.NewEvaluator(ng.Cfg, ng.Log, ng.DataSourceCache, ng.SecretsService),
@@ -131,7 +113,7 @@ func (ng *AlertNG) init() error {
Metrics: ng.Metrics.GetSchedulerMetrics(),
AdminConfigPollInterval: ng.Cfg.UnifiedAlerting.AdminConfigPollInterval,
DisabledOrgs: ng.Cfg.UnifiedAlerting.DisabledOrgs,
MinRuleInterval: ng.getRuleMinInterval(),
MinRuleInterval: ng.Cfg.UnifiedAlerting.MinInterval,
}
appUrl, err := url.Parse(ng.Cfg.AppURL)
@@ -191,30 +173,3 @@ func (ng *AlertNG) IsDisabled() bool {
}
return !ng.Cfg.UnifiedAlerting.IsEnabled()
}
// getRuleDefaultIntervalSeconds returns the default rule interval if the interval is not set.
// If this constant (1 minute) is lower than the configured minimum evaluation interval then
// this configuration is returned.
func (ng *AlertNG) getRuleDefaultInterval() time.Duration {
ruleMinInterval := ng.getRuleMinInterval()
if defaultIntervalSeconds < int64(ruleMinInterval.Seconds()) {
return ruleMinInterval
}
return time.Duration(defaultIntervalSeconds) * time.Second
}
// getRuleMinIntervalSeconds returns the configured minimum rule interval.
// If this value is less or equal to zero or not divided exactly by the scheduler interval
// the scheduler interval (10 seconds) is returned.
func (ng *AlertNG) getRuleMinInterval() time.Duration {
if ng.Cfg.UnifiedAlerting.MinInterval <= 0 {
return defaultBaseIntervalSeconds // if it's not configured; apply default
}
if ng.Cfg.UnifiedAlerting.MinInterval%defaultBaseIntervalSeconds != 0 {
ng.Log.Error("Configured minimum evaluation interval is not divided exactly by the scheduler interval and it will fallback to default", "alertingMinInterval", ng.Cfg.UnifiedAlerting.MinInterval, "baseIntervalSeconds", defaultBaseIntervalSeconds, "defaultIntervalSeconds", defaultIntervalSeconds)
return defaultBaseIntervalSeconds // if it's invalid; apply default
}
return ng.Cfg.UnifiedAlerting.MinInterval
}

View File

@@ -1,73 +0,0 @@
package ngalert
import (
"testing"
"time"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
func TestGetRuleDefaultIntervalSeconds(t *testing.T) {
testCases := []struct {
desc string
alertingMinIntervalCfg time.Duration
// the expected default rule interval (applied if a rule interval is missing)
expDefaultInterval time.Duration
// the expected minimum rule interval (enforced if a rule interval is lower than this value; it is used also for computing the default rule interval)
expMinInterval time.Duration
}{
{
desc: "negative min rule interval",
alertingMinIntervalCfg: -1,
expDefaultInterval: time.Duration(defaultIntervalSeconds) * time.Second, // 60s
expMinInterval: defaultBaseIntervalSeconds, // 10s
},
{
desc: "zero min rule interval",
alertingMinIntervalCfg: 0,
expDefaultInterval: time.Duration(defaultIntervalSeconds) * time.Second, // 60s
expMinInterval: defaultBaseIntervalSeconds, // 10s
},
{
desc: "min rule interval not divided exactly by the scheduler interval",
alertingMinIntervalCfg: 1,
expDefaultInterval: time.Duration(defaultIntervalSeconds) * time.Second, // 60s
expMinInterval: defaultBaseIntervalSeconds, // 10s
},
{
desc: "min rule interval equals base scheduler interval",
alertingMinIntervalCfg: defaultBaseIntervalSeconds, // 10s
expDefaultInterval: time.Duration(defaultIntervalSeconds) * time.Second, // 60s
expMinInterval: defaultBaseIntervalSeconds, // 10s
},
{
desc: "valid min rule interval less than default rule interval",
alertingMinIntervalCfg: time.Duration(defaultIntervalSeconds-defaultBaseIntervalSeconds) * time.Second, // 50s
expDefaultInterval: time.Duration(defaultIntervalSeconds) * time.Second, // 60s
expMinInterval: time.Duration(defaultIntervalSeconds-defaultBaseIntervalSeconds) * time.Second, // 50s
},
{
desc: "valid min rule interval greater than default rule interval",
alertingMinIntervalCfg: time.Duration(defaultIntervalSeconds+defaultBaseIntervalSeconds) * time.Second, // 70s
expDefaultInterval: time.Duration(defaultIntervalSeconds+defaultBaseIntervalSeconds) * time.Second, // 70s
expMinInterval: time.Duration(defaultIntervalSeconds+defaultBaseIntervalSeconds) * time.Second, // 70s
},
}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
alertNG := AlertNG{
Log: log.New("test"),
Cfg: &setting.Cfg{
UnifiedAlerting: setting.UnifiedAlertingSettings{
MinInterval: tc.alertingMinIntervalCfg,
},
},
}
require.Equal(t, tc.expDefaultInterval, alertNG.getRuleDefaultInterval())
require.Equal(t, tc.expMinInterval, alertNG.getRuleMinInterval())
})
}
}

View File

@@ -30,7 +30,9 @@ func SetupTestEnv(t *testing.T, baseInterval time.Duration) (*ngalert.AlertNG, *
t.Helper()
cfg := setting.NewCfg()
cfg.AlertingBaseInterval = baseInterval
cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{
BaseInterval: setting.SchedulerBaseInterval,
}
// AlertNG database migrations run and the relative database tables are created only when it's enabled
cfg.UnifiedAlerting.Enabled = new(bool)
*cfg.UnifiedAlerting.Enabled = true