Alerting: Add compact model for alert rules

This commit is contained in:
Santiago Hernández
2025-12-12 15:51:41 +01:00
parent b863acab05
commit 4e68e5e2ce
2 changed files with 45 additions and 5 deletions
+33 -5
View File
@@ -10,11 +10,38 @@ import (
"github.com/grafana/grafana/pkg/services/ngalert/models"
)
// We only care about the data source UIDs.
type compactQuery struct {
DatasourceUID string `json:"datasourceUid"`
}
func alertRuleToModelsAlertRule(ar alertRule, l log.Logger) (models.AlertRule, error) {
return transformRule(ar, l, false)
}
// alertRuleToModelsAlertRuleCompact transforms an alertRule to a models.AlertRule
// ignoring alert queries (except for data source UIDs), notification settings, and metadata.
func alertRuleToModelsAlertRuleCompact(ar alertRule, l log.Logger) (models.AlertRule, error) {
return transformRule(ar, l, true)
}
// transformRule creates a models.AlertRule from an alertRule.
// When 'compact' is set to 'true', it skips parsing the alert queries (except for the data source UID), notification
// settings, and metadata, thus reducing the number of JSON serializations needed.
func transformRule(ar alertRule, l log.Logger, compact bool) (models.AlertRule, error) {
var data []models.AlertQuery
err := json.Unmarshal([]byte(ar.Data), &data)
if err != nil {
return models.AlertRule{}, fmt.Errorf("failed to parse data: %w", err)
if compact {
var cqs []compactQuery
if err := json.Unmarshal([]byte(ar.Data), &cqs); err != nil {
return models.AlertRule{}, fmt.Errorf("failed to parse data: %w", err)
}
for _, cq := range cqs {
data = append(data, models.AlertQuery{DatasourceUID: cq.DatasourceUID})
}
} else {
if err := json.Unmarshal([]byte(ar.Data), &data); err != nil {
return models.AlertRule{}, fmt.Errorf("failed to parse data: %w", err)
}
}
result := models.AlertRule{
@@ -52,6 +79,7 @@ func alertRuleToModelsAlertRule(ar alertRule, l log.Logger) (models.AlertRule, e
result.UpdatedBy = util.Pointer(models.UserUID(*ar.UpdatedBy))
}
var err error
if ar.NoDataState != "" {
result.NoDataState, err = models.NoDataStateFromString(ar.NoDataState)
if err != nil {
@@ -90,7 +118,7 @@ func alertRuleToModelsAlertRule(ar alertRule, l log.Logger) (models.AlertRule, e
}
}
if ar.NotificationSettings != "" {
if !compact && ar.NotificationSettings != "" {
ns, err := parseNotificationSettings(ar.NotificationSettings)
if err != nil {
return models.AlertRule{}, fmt.Errorf("failed to parse notification settings: %w", err)
@@ -98,7 +126,7 @@ func alertRuleToModelsAlertRule(ar alertRule, l log.Logger) (models.AlertRule, e
result.NotificationSettings = ns
}
if ar.Metadata != "" {
if !compact && ar.Metadata != "" {
err = json.Unmarshal([]byte(ar.Metadata), &result.Metadata)
if err != nil {
return models.AlertRule{}, fmt.Errorf("failed to metadata: %w", err)
+12
View File
@@ -5,6 +5,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/log/logtest"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/util"
@@ -81,3 +82,14 @@ func TestAlertRuleVersionToAlertRule(t *testing.T) {
}
})
}
func BenchmarkAlertRuleToModelsAlertRule(b *testing.B) {
r := ngmodels.RuleGen.Generate()
ar, err := alertRuleFromModelsAlertRule(r)
require.NoError(b, err)
l := log.NewNopLogger()
for range b.N {
alertRuleToModelsAlertRuleCompact(ar, l)
}
}