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" "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) { 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 var data []models.AlertQuery
err := json.Unmarshal([]byte(ar.Data), &data) if compact {
if err != nil { var cqs []compactQuery
return models.AlertRule{}, fmt.Errorf("failed to parse data: %w", err) 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{ 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)) result.UpdatedBy = util.Pointer(models.UserUID(*ar.UpdatedBy))
} }
var err error
if ar.NoDataState != "" { if ar.NoDataState != "" {
result.NoDataState, err = models.NoDataStateFromString(ar.NoDataState) result.NoDataState, err = models.NoDataStateFromString(ar.NoDataState)
if err != nil { 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) ns, err := parseNotificationSettings(ar.NotificationSettings)
if err != nil { if err != nil {
return models.AlertRule{}, fmt.Errorf("failed to parse notification settings: %w", err) 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 result.NotificationSettings = ns
} }
if ar.Metadata != "" { if !compact && ar.Metadata != "" {
err = json.Unmarshal([]byte(ar.Metadata), &result.Metadata) err = json.Unmarshal([]byte(ar.Metadata), &result.Metadata)
if err != nil { if err != nil {
return models.AlertRule{}, fmt.Errorf("failed to metadata: %w", err) 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/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/log/logtest" "github.com/grafana/grafana/pkg/infra/log/logtest"
ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models"
"github.com/grafana/grafana/pkg/util" "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)
}
}