[v9.5.x] Alerting: Migrate unknown NoData\Error settings to the default (#70905)

Alerting: Migrate unknown NoData\Error settings to the default (#68403)

* use default execution if legacy is not known

* update docs

* Update docs/sources/alerting/migrating-alerts/migrating-legacy-alerts.md

Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com>

* Update docs/sources/alerting/migrating-alerts/migrating-legacy-alerts.md

Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com>

---------

Co-authored-by: brendamuir <100768211+brendamuir@users.noreply.github.com>
(cherry picked from commit 3af95bebe1)

Co-authored-by: Yuri Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
grafana-delivery-bot[bot]
2023-06-29 10:55:05 -04:00
committed by GitHub
co-authored by Yuri Tseretyan
parent 7f6a309614
commit b585067281
3 changed files with 49 additions and 27 deletions
@@ -6,6 +6,7 @@ import (
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
legacymodels "github.com/grafana/grafana/pkg/services/alerting/models"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/tsdb/graphite"
@@ -105,7 +106,7 @@ func addMigrationInfo(da *dashAlert) (map[string]string, map[string]string) {
return lbls, annotations
}
func (m *migration) makeAlertRule(cond condition, da dashAlert, folderUID string) (*alertRule, error) {
func (m *migration) makeAlertRule(l log.Logger, cond condition, da dashAlert, folderUID string) (*alertRule, error) {
lbls, annotations := addMigrationInfo(&da)
annotations["message"] = da.Message
var err error
@@ -143,16 +144,8 @@ func (m *migration) makeAlertRule(cond condition, da dashAlert, folderUID string
Labels: lbls,
RuleGroupIndex: 1,
IsPaused: isPaused,
}
ar.NoDataState, err = transNoData(da.ParsedSettings.NoDataState)
if err != nil {
return nil, err
}
ar.ExecErrState, err = transExecErr(da.ParsedSettings.ExecutionErrorState)
if err != nil {
return nil, err
NoDataState: transNoData(l, da.ParsedSettings.NoDataState),
ExecErrState: transExecErr(l, da.ParsedSettings.ExecutionErrorState),
}
// Label for routing and silences.
@@ -271,32 +264,36 @@ func ruleAdjustInterval(freq int64) int64 {
return freq - (freq % baseFreq)
}
func transNoData(s string) (string, error) {
func transNoData(l log.Logger, s string) string {
switch legacymodels.NoDataOption(s) {
case legacymodels.NoDataSetOK:
return string(ngmodels.OK), nil // values from ngalert/models/rule
return string(ngmodels.OK) // values from ngalert/models/rule
case "", legacymodels.NoDataSetNoData:
return string(ngmodels.NoData), nil
return string(ngmodels.NoData)
case legacymodels.NoDataSetAlerting:
return string(ngmodels.Alerting), nil
return string(ngmodels.Alerting)
case legacymodels.NoDataKeepState:
return string(ngmodels.NoData), nil // "keep last state" translates to no data because we now emit a special alert when the state is "noData". The result is that the evaluation will not return firing and instead we'll raise the special alert.
return string(ngmodels.NoData) // "keep last state" translates to no data because we now emit a special alert when the state is "noData". The result is that the evaluation will not return firing and instead we'll raise the special alert.
default:
l.Warn("Unable to translate execution of NoData state. Using default execution", "old", s, "new", ngmodels.NoData)
return string(ngmodels.NoData)
}
return "", fmt.Errorf("unrecognized No Data setting %v", s)
}
func transExecErr(s string) (string, error) {
func transExecErr(l log.Logger, s string) string {
switch legacymodels.ExecutionErrorOption(s) {
case "", legacymodels.ExecutionErrorSetAlerting:
return string(ngmodels.AlertingErrState), nil
return string(ngmodels.AlertingErrState)
case legacymodels.ExecutionErrorKeepState:
// Keep last state is translated to error as we now emit a
// DatasourceError alert when the state is error
return string(ngmodels.ErrorErrState), nil
return string(ngmodels.ErrorErrState)
case legacymodels.ExecutionErrorSetOk:
return string(ngmodels.OkErrState), nil
return string(ngmodels.OkErrState)
default:
l.Warn("Unable to translate execution of Error state. Using default execution", "old", s, "new", ngmodels.ErrorErrState)
return string(ngmodels.ErrorErrState)
}
return "", fmt.Errorf("unrecognized Execution Error setting %v", s)
}
func normalizeRuleName(daName string, uid string) string {
@@ -5,9 +5,12 @@ import (
"strings"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log/logtest"
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
func TestMigrateAlertRuleQueries(t *testing.T) {
@@ -93,7 +96,7 @@ func TestMakeAlertRule(t *testing.T) {
da := createTestDashAlert()
cnd := createTestDashAlertCondition()
ar, err := m.makeAlertRule(cnd, da, "folder")
ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder")
require.NoError(t, err)
require.Equal(t, da.Name, ar.Title)
@@ -106,7 +109,7 @@ func TestMakeAlertRule(t *testing.T) {
da.Name = strings.Repeat("a", DefaultFieldMaxLength+1)
cnd := createTestDashAlertCondition()
ar, err := m.makeAlertRule(cnd, da, "folder")
ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder")
require.NoError(t, err)
require.Len(t, ar.Title, DefaultFieldMaxLength)
@@ -123,7 +126,7 @@ func TestMakeAlertRule(t *testing.T) {
da := createTestDashAlert()
cnd := createTestDashAlertCondition()
ar, err := m.makeAlertRule(cnd, da, "folder")
ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder")
require.NoError(t, err)
require.False(t, ar.IsPaused)
})
@@ -134,10 +137,32 @@ func TestMakeAlertRule(t *testing.T) {
da.State = "paused"
cnd := createTestDashAlertCondition()
ar, err := m.makeAlertRule(cnd, da, "folder")
ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder")
require.NoError(t, err)
require.True(t, ar.IsPaused)
})
t.Run("use default if execution of NoData is not known", func(t *testing.T) {
m := newTestMigration(t)
da := createTestDashAlert()
da.ParsedSettings.NoDataState = uuid.NewString()
cnd := createTestDashAlertCondition()
ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder")
require.Nil(t, err)
require.Equal(t, string(models.NoData), ar.NoDataState)
})
t.Run("use default if execution of Error is not known", func(t *testing.T) {
m := newTestMigration(t)
da := createTestDashAlert()
da.ParsedSettings.ExecutionErrorState = uuid.NewString()
cnd := createTestDashAlertCondition()
ar, err := m.makeAlertRule(&logtest.Fake{}, cnd, da, "folder")
require.Nil(t, err)
require.Equal(t, string(models.ErrorErrState), ar.ExecErrState)
})
}
func createTestDashAlert() dashAlert {
@@ -377,7 +377,7 @@ func (m *migration) Exec(sess *xorm.Session, mg *migrator.Migrator) error {
AlertId: da.Id,
}
}
rule, err := m.makeAlertRule(*newCond, da, folder.Uid)
rule, err := m.makeAlertRule(l, *newCond, da, folder.Uid)
if err != nil {
return err
}