- {(ruleFormType === RuleFormType.cloudRecording || ruleFormType === RuleFormType.cloudAlerting) && (
+ {(ruleFormType === RuleFormType.cloudAlerting || ruleFormType === RuleFormType.cloudRecording) && (
{
const runner = useRef(new AlertingQueryRunner());
+
const {
setValue,
getValues,
@@ -53,15 +57,15 @@ export const QueryAndExpressionsStep = ({ editingExistingRule, onDataChange }: P
queries: getValues('queries'),
panelData: {},
};
- const [{ queries }, dispatch] = useReducer(queriesAndExpressionsReducer, initialState);
+ const [{ queries }, dispatch] = useReducer(queriesAndExpressionsReducer, initialState);
const [type, condition, dataSourceName] = watch(['type', 'condition', 'dataSourceName']);
const isGrafanaManagedType = type === RuleFormType.grafana;
- const isCloudAlertRuleType = type === RuleFormType.cloudAlerting;
const isRecordingRuleType = type === RuleFormType.cloudRecording;
+ const isCloudAlertRuleType = type === RuleFormType.cloudAlerting;
- const showCloudExpressionEditor = (isRecordingRuleType || isCloudAlertRuleType) && dataSourceName;
+ const rulesSourcesWithRuler = useRulesSourcesWithRuler();
const cancelQueries = useCallback(() => {
runner.current.cancel();
@@ -108,7 +112,7 @@ export const QueryAndExpressionsStep = ({ editingExistingRule, onDataChange }: P
useEffect(() => {
const currentCondition = getValues('condition');
- if (!currentCondition) {
+ if (!currentCondition || RuleFormType.cloudRecording) {
return;
}
@@ -164,6 +168,43 @@ export const QueryAndExpressionsStep = ({ editingExistingRule, onDataChange }: P
[queries]
);
+ const onChangeRecordingRulesQueries = useCallback(
+ (updatedQueries) => {
+ const dataSourceSettings = getDataSourceSrv().getInstanceSettings(updatedQueries[0].datasourceUid);
+ if (!dataSourceSettings) {
+ throw new Error('The Data source has not been defined.');
+ }
+
+ const expression = updatedQueries[0].model?.expr || '';
+
+ setValue('dataSourceName', dataSourceSettings.name);
+ setValue('expression', expression);
+
+ dispatch(setRecordingRulesQueries({ recordingRuleQueries: updatedQueries, expression }));
+ runQueries();
+ },
+ [runQueries, setValue]
+ );
+
+ const recordingRuleDefaultDatasource = rulesSourcesWithRuler[0];
+
+ useEffect(() => {
+ setPanelData({});
+ if (type === RuleFormType.cloudRecording) {
+ const defaultQuery = {
+ refId: 'A',
+ datasourceUid: recordingRuleDefaultDatasource.uid,
+ queryType: '',
+ relativeTimeRange: getDefaultRelativeTimeRange(),
+ model: {
+ refId: 'A',
+ hide: false,
+ },
+ };
+ dispatch(setRecordingRulesQueries({ recordingRuleQueries: [defaultQuery], expression: getValues('expression') }));
+ }
+ }, [type, recordingRuleDefaultDatasource, editingExistingRule, getValues]);
+
const onDuplicateQuery = useCallback((query: AlertQuery) => {
dispatch(duplicateQuery(query));
}, []);
@@ -180,8 +221,21 @@ export const QueryAndExpressionsStep = ({ editingExistingRule, onDataChange }: P
- {/* This is the PromQL Editor for Cloud rules and recording rules */}
- {showCloudExpressionEditor && (
+ {/* This is the PromQL Editor for recording rules */}
+ {isRecordingRuleType && dataSourceName && (
+
+
+
+ )}
+
+ {/* This is the PromQL Editor for Cloud rules */}
+ {isCloudAlertRuleType && dataSourceName && (
('updateMaxDataPoints');
+export const setRecordingRulesQueries = createAction<{ recordingRuleQueries: AlertQuery[]; expression: string }>(
+ 'setRecordingRulesQueries'
+);
+
export const queriesAndExpressionsReducer = createReducer(initialState, (builder) => {
// data queries actions
builder
@@ -69,6 +73,15 @@ export const queriesAndExpressionsReducer = createReducer(initialState, (builder
const expressionQueries = state.queries.filter((query) => isExpressionQuery(query.model));
state.queries = [...payload, ...expressionQueries];
})
+ .addCase(setRecordingRulesQueries, (state, { payload }) => {
+ const query = payload.recordingRuleQueries[0];
+ const recordingRuleQuery = {
+ ...query,
+ ...{ expr: payload.expression, model: { expr: payload.expression, refId: query.model.refId } },
+ };
+
+ state.queries = [recordingRuleQuery];
+ })
.addCase(updateMaxDataPoints, (state, action) => {
state.queries = state.queries.map((query) => {
return query.refId === action.payload.refId
diff --git a/public/app/features/alerting/unified/utils/rule-form.ts b/public/app/features/alerting/unified/utils/rule-form.ts
index 339dd0ca46f..f369ee5bbb2 100644
--- a/public/app/features/alerting/unified/utils/rule-form.ts
+++ b/public/app/features/alerting/unified/utils/rule-form.ts
@@ -7,9 +7,11 @@ import {
RelativeTimeRange,
ScopedVars,
TimeRange,
+ DataSourceInstanceSettings,
} from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
+import { DataSourceJsonData } from '@grafana/schema';
import { getNextRefIdChar } from 'app/core/utils/query';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { ExpressionQuery, ExpressionQueryType, ExpressionDatasourceUID } from 'app/features/expressions/types';
@@ -56,6 +58,7 @@ export const getDefaultFormValues = (): RuleFormValues => {
// grafana
folder: null,
queries: [],
+ recordingRulesQueries: [],
condition: '',
noDataState: GrafanaAlertStateDecision.NoData,
execErrState: GrafanaAlertStateDecision.Error,
@@ -221,6 +224,25 @@ export const getDefaultQueries = (): AlertQuery[] => {
];
};
+export const getDefaultRecordingRulesQueries = (
+ rulesSourcesWithRuler: Array>
+): AlertQuery[] => {
+ const relativeTimeRange = getDefaultRelativeTimeRange();
+
+ return [
+ {
+ refId: 'A',
+ datasourceUid: rulesSourcesWithRuler[0]?.uid || '',
+ queryType: '',
+ relativeTimeRange,
+ model: {
+ refId: 'A',
+ hide: false,
+ },
+ },
+ ];
+};
+
const getDefaultExpressions = (...refIds: [string, string]): AlertQuery[] => {
const refOne = refIds[0];
const refTwo = refIds[1];