Skip to content

Commit dc12e0c

Browse files
committed
feat(FR-2494): add Prometheus query result preview in editor modal
1 parent 9c9286d commit dc12e0c

2 files changed

Lines changed: 113 additions & 1 deletion

File tree

react/src/components/AutoScalingRuleEditorModal.tsx

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,22 @@ import {
77
AutoScalingRuleEditorModalFragment$data,
88
AutoScalingRuleEditorModalFragment$key,
99
} from '../__generated__/AutoScalingRuleEditorModalFragment.graphql';
10+
import { AutoScalingRuleEditorModalPresetResultQuery } from '../__generated__/AutoScalingRuleEditorModalPresetResultQuery.graphql';
1011
import { AutoScalingRuleEditorModalPresetsQuery } from '../__generated__/AutoScalingRuleEditorModalPresetsQuery.graphql';
1112
import { AutoScalingRuleEditorModalUpdateMutation } from '../__generated__/AutoScalingRuleEditorModalUpdateMutation.graphql';
1213
import { SIGNED_32BIT_MAX_INT } from '../helper/const-vars';
14+
import ErrorBoundaryWithNullFallback from './ErrorBoundaryWithNullFallback';
15+
import { ReloadOutlined } from '@ant-design/icons';
1316
import {
1417
App,
1518
AutoComplete,
19+
Button,
1620
Form,
1721
FormInstance,
1822
InputNumber,
1923
Segmented,
2024
Select,
25+
Spin,
2126
Typography,
2227
} from 'antd';
2328
import {
@@ -71,6 +76,92 @@ const METRIC_NAMES_MAP: Partial<
7176
INFERENCE_FRAMEWORK: [],
7277
};
7378

79+
/**
80+
* Inline preview component that fetches and displays the current Prometheus
81+
* metric value for a selected preset. Uses useLazyLoadQuery with fetchKey
82+
* to support manual refresh without useEffect + setState.
83+
*/
84+
const PrometheusPresetPreview: React.FC<{
85+
presetGlobalId: string;
86+
}> = ({ presetGlobalId }) => {
87+
'use memo';
88+
const { t } = useTranslation();
89+
const [fetchKey, setFetchKey] = useState(0);
90+
91+
const presetRawId = toLocalId(presetGlobalId);
92+
93+
const data = useLazyLoadQuery<AutoScalingRuleEditorModalPresetResultQuery>(
94+
graphql`
95+
query AutoScalingRuleEditorModalPresetResultQuery(
96+
$id: ID!
97+
$options: ExecuteQueryDefinitionOptionsInput
98+
) {
99+
prometheusQueryPresetResult(id: $id, options: $options) {
100+
status
101+
resultType
102+
result {
103+
metric {
104+
key
105+
value
106+
}
107+
values {
108+
timestamp
109+
value
110+
}
111+
}
112+
}
113+
}
114+
`,
115+
{
116+
id: presetRawId,
117+
options: {
118+
filterLabels: [],
119+
groupLabels: [],
120+
},
121+
},
122+
{ fetchPolicy: 'network-only', fetchKey: `preview-${fetchKey}` },
123+
);
124+
125+
const results = data.prometheusQueryPresetResult.result;
126+
127+
let displayValue: string | null = null;
128+
if (results.length === 0) {
129+
displayValue = null;
130+
} else if (results.length === 1) {
131+
const values = results[0].values;
132+
displayValue = values.length > 0 ? values[values.length - 1].value : null;
133+
} else {
134+
const firstValues = results[0].values;
135+
const latestValue =
136+
firstValues.length > 0 ? firstValues[firstValues.length - 1].value : null;
137+
displayValue =
138+
latestValue != null
139+
? t('autoScalingRule.MultipleSeriesResult', {
140+
count: results.length,
141+
value: latestValue,
142+
})
143+
: null;
144+
}
145+
146+
return (
147+
<span>
148+
<Typography.Text type="secondary" style={{ marginRight: 4 }}>
149+
{t('autoScalingRule.CurrentValue')}:{' '}
150+
</Typography.Text>
151+
<Typography.Text strong>
152+
{displayValue ?? t('autoScalingRule.NoDataAvailable')}
153+
</Typography.Text>
154+
<Button
155+
type="link"
156+
size="small"
157+
icon={<ReloadOutlined />}
158+
onClick={() => setFetchKey((k) => k + 1)}
159+
title={t('autoScalingRule.RefreshPreview')}
160+
/>
161+
</span>
162+
);
163+
};
164+
74165
/**
75166
* Determines initial condition mode and direction from existing rule data.
76167
*/
@@ -512,7 +603,24 @@ const AutoScalingRuleEditorModal: React.FC<AutoScalingRuleEditorModalProps> = ({
512603
/>
513604
</Form.Item>
514605
{selectedPreset && (
515-
<Form.Item label={t('autoScalingRule.QueryTemplate')}>
606+
<Form.Item
607+
label={t('autoScalingRule.QueryTemplate')}
608+
extra={
609+
selectedPresetId ? (
610+
<ErrorBoundaryWithNullFallback>
611+
<React.Suspense
612+
fallback={
613+
<Spin size="small" style={{ marginRight: 8 }} />
614+
}
615+
>
616+
<PrometheusPresetPreview
617+
presetGlobalId={selectedPresetId}
618+
/>
619+
</React.Suspense>
620+
</ErrorBoundaryWithNullFallback>
621+
) : undefined
622+
}
623+
>
516624
<Typography.Text
517625
code
518626
style={{

resources/i18n/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
"ConfirmDeleteAutoScalingRule": "Are you sure to delete auto scaling rule {{ autoScalingRule }} ?",
158158
"CoolDownSeconds": "CoolDown Seconds",
159159
"CreatedAt": "Created At",
160+
"CurrentValue": "Current value",
160161
"EditAutoScalingRule": "Edit Auto Scaling Rule",
161162
"LastTriggered": "Last Triggered",
162163
"Lower": "Lower",
@@ -170,10 +171,13 @@
170171
"MinReplicas": "Min Replicas",
171172
"MinThreshold": "Min Threshold",
172173
"MinThresholdRequired": "Min threshold is required.",
174+
"MultipleSeriesResult": "{{count}} series found, latest: {{value}}",
175+
"NoDataAvailable": "No data available",
173176
"PrometheusPreset": "Prometheus Preset",
174177
"PrometheusPresetRequired": "Please select a Prometheus preset.",
175178
"QueryTemplate": "Query Template",
176179
"Range": "Range",
180+
"RefreshPreview": "Refresh preview",
177181
"ScaleIn": "Scale In",
178182
"ScaleOut": "Scale Out",
179183
"ScalingType": "Type",

0 commit comments

Comments
 (0)