Skip to content

Commit dfbddd8

Browse files
authored
Alerting: Fix recording rule export (grafana#91405)
* Fix HCL export * Update rule export struct to support new optional fields * Omit `for` field in export API if empty
1 parent 0038171 commit dfbddd8

File tree

7 files changed

+242
-16
lines changed

7 files changed

+242
-16
lines changed

pkg/services/ngalert/api/api_ruler_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ func createService(store *fakes.RuleStore) *RulerSrv {
653653
authz: accesscontrol.NewRuleService(acimpl.ProvideAccessControl(featuremgmt.WithFeatures(), zanzana.NewNoopClient())),
654654
amConfigStore: &fakeAMRefresher{},
655655
amRefresher: &fakeAMRefresher{},
656-
featureManager: featuremgmt.WithFeatures(),
656+
featureManager: featuremgmt.WithFeatures(featuremgmt.FlagGrafanaManagedRecordingRules),
657657
}
658658
}
659659

pkg/services/ngalert/api/compat.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,32 @@ func AlertRuleExportFromAlertRule(rule models.AlertRule) (definitions.AlertRuleE
179179
data = append(data, query)
180180
}
181181

182+
cPtr := &rule.Condition
183+
if rule.Condition == "" {
184+
cPtr = nil
185+
}
186+
187+
noDataState := definitions.NoDataState(rule.NoDataState)
188+
ndsPtr := &noDataState
189+
if noDataState == "" {
190+
ndsPtr = nil
191+
}
192+
execErrorState := definitions.ExecutionErrorState(rule.ExecErrState)
193+
eesPtr := &execErrorState
194+
if execErrorState == "" {
195+
eesPtr = nil
196+
}
197+
182198
result := definitions.AlertRuleExport{
183199
UID: rule.UID,
184200
Title: rule.Title,
185201
For: model.Duration(rule.For),
186-
Condition: rule.Condition,
202+
Condition: cPtr,
187203
Data: data,
188204
DashboardUID: rule.DashboardUID,
189205
PanelID: rule.PanelID,
190-
NoDataState: definitions.NoDataState(rule.NoDataState),
191-
ExecErrState: definitions.ExecutionErrorState(rule.ExecErrState),
206+
NoDataState: ndsPtr,
207+
ExecErrState: eesPtr,
192208
IsPaused: rule.IsPaused,
193209
NotificationSettings: AlertRuleNotificationSettingsExportFromNotificationSettings(rule.NotificationSettings),
194210
Record: AlertRuleRecordExportFromRecord(rule.Record),

pkg/services/ngalert/api/test-data/post-rulegroup-101-export.hcl

+44
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,48 @@ resource "grafana_rule_group" "rule_group_d3e8424bfbf66bc3" {
8787
mute_timings = ["test-mute"]
8888
}
8989
}
90+
rule {
91+
name = "recording rule"
92+
93+
data {
94+
ref_id = "query"
95+
96+
relative_time_range {
97+
from = 18000
98+
to = 10800
99+
}
100+
101+
datasource_uid = "000000002"
102+
model = "{\"expr\":\"http_request_duration_microseconds_count\",\"hide\":false,\"interval\":\"\",\"intervalMs\":1000,\"legendFormat\":\"\",\"maxDataPoints\":100,\"refId\":\"query\"}"
103+
}
104+
data {
105+
ref_id = "reduced"
106+
107+
relative_time_range {
108+
from = 18000
109+
to = 10800
110+
}
111+
112+
datasource_uid = "__expr__"
113+
model = "{\"expression\":\"query\",\"hide\":false,\"intervalMs\":1000,\"maxDataPoints\":100,\"reducer\":\"mean\",\"refId\":\"reduced\",\"type\":\"reduce\"}"
114+
}
115+
data {
116+
ref_id = "condition"
117+
118+
relative_time_range {
119+
from = 18000
120+
to = 10800
121+
}
122+
123+
datasource_uid = "__expr__"
124+
model = "{\"expression\":\"$reduced > 10\",\"hide\":false,\"intervalMs\":1000,\"maxDataPoints\":100,\"refId\":\"condition\",\"type\":\"math\"}"
125+
}
126+
127+
is_paused = false
128+
129+
record {
130+
metric = "test_metric"
131+
from = "condition"
132+
}
133+
}
90134
}

pkg/services/ngalert/api/test-data/post-rulegroup-101-export.json

+60-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@
108108
],
109109
"noDataState": "NoData",
110110
"execErrState": "Alerting",
111-
"for": "0s",
112111
"isPaused": false,
113112
"notification_settings":{
114113
"receiver":"Test-Receiver",
@@ -118,6 +117,66 @@
118117
"repeat_interval":"5m",
119118
"mute_time_intervals":["test-mute"]
120119
}
120+
},
121+
{
122+
"title": "recording rule",
123+
"data": [
124+
{
125+
"refId": "query",
126+
"relativeTimeRange": {
127+
"from": 18000,
128+
"to": 10800
129+
},
130+
"datasourceUid": "000000002",
131+
"model": {
132+
"expr": "http_request_duration_microseconds_count",
133+
"hide": false,
134+
"interval": "",
135+
"intervalMs": 1000,
136+
"legendFormat": "",
137+
"maxDataPoints": 100,
138+
"refId": "query"
139+
}
140+
},
141+
{
142+
"refId": "reduced",
143+
"relativeTimeRange": {
144+
"from": 18000,
145+
"to": 10800
146+
},
147+
"datasourceUid": "__expr__",
148+
"model": {
149+
"expression": "query",
150+
"hide": false,
151+
"intervalMs": 1000,
152+
"maxDataPoints": 100,
153+
"reducer": "mean",
154+
"refId": "reduced",
155+
"type": "reduce"
156+
}
157+
},
158+
{
159+
"refId": "condition",
160+
"relativeTimeRange": {
161+
"from": 18000,
162+
"to": 10800
163+
},
164+
"datasourceUid": "__expr__",
165+
"model": {
166+
"expression": "$reduced \u003e 10",
167+
"hide": false,
168+
"intervalMs": 1000,
169+
"maxDataPoints": 100,
170+
"refId": "condition",
171+
"type": "math"
172+
}
173+
}
174+
],
175+
"isPaused": false,
176+
"record": {
177+
"metric": "test_metric",
178+
"from": "condition"
179+
}
121180
}
122181
]
123182
}

pkg/services/ngalert/api/test-data/post-rulegroup-101-export.yaml

+44-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ groups:
8181
type: reduce
8282
noDataState: NoData
8383
execErrState: Alerting
84-
for: 0s
8584
isPaused: false
8685
notification_settings:
8786
receiver: Test-Receiver
@@ -94,3 +93,47 @@ groups:
9493
repeat_interval: 5m
9594
mute_time_intervals:
9695
- test-mute
96+
- title: recording rule
97+
data:
98+
- refId: query
99+
relativeTimeRange:
100+
from: 18000
101+
to: 10800
102+
datasourceUid: "000000002"
103+
model:
104+
expr: http_request_duration_microseconds_count
105+
hide: false
106+
interval: ""
107+
intervalMs: 1000
108+
legendFormat: ""
109+
maxDataPoints: 100
110+
refId: query
111+
- refId: reduced
112+
relativeTimeRange:
113+
from: 18000
114+
to: 10800
115+
datasourceUid: __expr__
116+
model:
117+
expression: query
118+
hide: false
119+
intervalMs: 1000
120+
maxDataPoints: 100
121+
reducer: mean
122+
refId: reduced
123+
type: reduce
124+
- refId: condition
125+
relativeTimeRange:
126+
from: 18000
127+
to: 10800
128+
datasourceUid: __expr__
129+
model:
130+
expression: $reduced > 10
131+
hide: false
132+
intervalMs: 1000
133+
maxDataPoints: 100
134+
refId: condition
135+
type: math
136+
isPaused: false
137+
record:
138+
metric: test_metric
139+
from: condition

pkg/services/ngalert/api/test-data/post-rulegroup-101.json

+64
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,70 @@
119119
"mute_time_intervals":["test-mute"]
120120
}
121121
}
122+
},
123+
{
124+
"grafana_alert": {
125+
"title": "recording rule",
126+
"data": [
127+
{
128+
"refId": "query",
129+
"queryType": "",
130+
"relativeTimeRange": {
131+
"from": 18000,
132+
"to": 10800
133+
},
134+
"datasourceUid": "000000002",
135+
"model": {
136+
"expr": "http_request_duration_microseconds_count",
137+
"hide": false,
138+
"interval": "",
139+
"intervalMs": 1000,
140+
"legendFormat": "",
141+
"maxDataPoints": 100,
142+
"refId": "query"
143+
}
144+
},
145+
{
146+
"refId": "reduced",
147+
"queryType": "",
148+
"relativeTimeRange": {
149+
"from": 18000,
150+
"to": 10800
151+
},
152+
"datasourceUid": "__expr__",
153+
"model": {
154+
"expression": "query",
155+
"hide": false,
156+
"intervalMs": 1000,
157+
"maxDataPoints": 100,
158+
"reducer": "mean",
159+
"refId": "reduced",
160+
"type": "reduce"
161+
}
162+
},
163+
{
164+
"refId": "condition",
165+
"queryType": "",
166+
"relativeTimeRange": {
167+
"from": 18000,
168+
"to": 10800
169+
},
170+
"datasourceUid": "__expr__",
171+
"model": {
172+
"expression": "$reduced > 10",
173+
"hide": false,
174+
"intervalMs": 1000,
175+
"maxDataPoints": 100,
176+
"refId": "condition",
177+
"type": "math"
178+
}
179+
}
180+
],
181+
"record": {
182+
"metric": "test_metric",
183+
"from": "condition"
184+
}
185+
}
122186
}
123187
]
124188
}

pkg/services/ngalert/api/tooling/definitions/provisioning_alert_rules.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,15 @@ type AlertRuleGroupExport struct {
258258

259259
// AlertRuleExport is the provisioned file export of models.AlertRule.
260260
type AlertRuleExport struct {
261-
UID string `json:"uid,omitempty" yaml:"uid,omitempty"`
262-
Title string `json:"title" yaml:"title" hcl:"name"`
263-
Condition string `json:"condition" yaml:"condition" hcl:"condition"`
264-
Data []AlertQueryExport `json:"data" yaml:"data" hcl:"data,block"`
265-
DashboardUID *string `json:"dashboardUid,omitempty" yaml:"dashboardUid,omitempty"`
266-
PanelID *int64 `json:"panelId,omitempty" yaml:"panelId,omitempty"`
267-
NoDataState NoDataState `json:"noDataState" yaml:"noDataState" hcl:"no_data_state"`
268-
ExecErrState ExecutionErrorState `json:"execErrState" yaml:"execErrState" hcl:"exec_err_state"`
269-
For model.Duration `json:"for" yaml:"for"`
261+
UID string `json:"uid,omitempty" yaml:"uid,omitempty"`
262+
Title string `json:"title" yaml:"title" hcl:"name"`
263+
Condition *string `json:"condition,omitempty" yaml:"condition,omitempty" hcl:"condition"`
264+
Data []AlertQueryExport `json:"data" yaml:"data" hcl:"data,block"`
265+
DashboardUID *string `json:"dashboardUid,omitempty" yaml:"dashboardUid,omitempty"`
266+
PanelID *int64 `json:"panelId,omitempty" yaml:"panelId,omitempty"`
267+
NoDataState *NoDataState `json:"noDataState,omitempty" yaml:"noDataState,omitempty" hcl:"no_data_state"`
268+
ExecErrState *ExecutionErrorState `json:"execErrState,omitempty" yaml:"execErrState,omitempty" hcl:"exec_err_state"`
269+
For model.Duration `json:"for,omitempty" yaml:"for,omitempty"`
270270
// ForString is used to:
271271
// - Only export the for field for HCL if it is non-zero.
272272
// - Format the Prometheus model.Duration type properly for HCL.
@@ -275,7 +275,7 @@ type AlertRuleExport struct {
275275
Labels *map[string]string `json:"labels,omitempty" yaml:"labels,omitempty" hcl:"labels"`
276276
IsPaused bool `json:"isPaused" yaml:"isPaused" hcl:"is_paused"`
277277
NotificationSettings *AlertRuleNotificationSettingsExport `json:"notification_settings,omitempty" yaml:"notification_settings,omitempty" hcl:"notification_settings,block"`
278-
Record *AlertRuleRecordExport `json:"record,omitempty" yaml:"record,omitempty" hcl:"record"`
278+
Record *AlertRuleRecordExport `json:"record,omitempty" yaml:"record,omitempty" hcl:"record,block"`
279279
}
280280

281281
// AlertQueryExport is the provisioned export of models.AlertQuery.

0 commit comments

Comments
 (0)