Skip to content

Commit 951876b

Browse files
authored
Prometheus: Add classic query option to variable query editor (grafana#74060)
* add classic query to variable query editor * copy fixes * update test
1 parent 0f55205 commit 951876b

File tree

5 files changed

+104
-21
lines changed

5 files changed

+104
-21
lines changed

docs/sources/datasources/prometheus/template-variables/index.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ You have the option to use several different variable types, but variables of th
3131

3232
Select a Prometheus data source query type and enter the required inputs:
3333

34-
| Query Type | Input(\* required) | Description | Used API endpoints |
35-
| -------------- | ------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------- |
36-
| `Label names` | `metric` | Returns a list of all label names matching the specified `metric` regex. | /api/v1/labels |
37-
| `Label values` | `label`\*, `metric` | Returns a list of label values for the `label` in all metrics or the optional metric. | /api/v1/label/`label`/values or /api/v1/series |
38-
| `Metrics` | `metric` | Returns a list of metrics matching the specified `metric` regex. | /api/v1/label/\_\_name\_\_/values |
39-
| `Query result` | `query` | Returns a list of Prometheus query result for the `query`. | /api/v1/query |
40-
| `Series query` | `metric`, `label` or both | Returns a list of time series associated with the entered data. | /api/v1/series |
34+
| Query Type | Input(\* required) | Description | Used API endpoints |
35+
| --------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- |
36+
| `Label names` | `metric` | Returns a list of all label names matching the specified `metric` regex. | /api/v1/labels |
37+
| `Label values` | `label`\*, `metric` | Returns a list of label values for the `label` in all metrics or the optional metric. | /api/v1/label/`label`/values or /api/v1/series |
38+
| `Metrics` | `metric` | Returns a list of metrics matching the specified `metric` regex. | /api/v1/label/\_\_name\_\_/values |
39+
| `Query result` | `query` | Returns a list of Prometheus query result for the `query`. | /api/v1/query |
40+
| `Series query` | `metric`, `label` or both | Returns a list of time series associated with the entered data. | /api/v1/series |
41+
| `Classic query` | classic query string | Deprecated, classic version of variable query editor. Enter a string with the query type using a syntax like the following: `label_values(<metric>, <label>)` | all |
4142

4243
For details on _metric names_, _label names_, and _label values_, refer to the [Prometheus documentation](http://prometheus.io/docs/concepts/data_model/#metric-names-and-labels).
4344

public/app/plugins/datasource/prometheus/components/VariableQueryEditor.test.tsx

+34-2
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ describe('PromVariableQueryEditor', () => {
149149
await waitFor(() => expect(screen.getByText('Metrics')).toBeInTheDocument());
150150
await waitFor(() => expect(screen.getByText('Query result')).toBeInTheDocument());
151151
await waitFor(() => expect(screen.getByText('Series query')).toBeInTheDocument());
152+
await waitFor(() => expect(screen.getByText('Classic query')).toBeInTheDocument());
152153
});
153154

154155
test('Calls onChange for label_names(match) query', async () => {
@@ -167,10 +168,11 @@ describe('PromVariableQueryEditor', () => {
167168
expect(onChange).toHaveBeenCalledWith({
168169
query: 'label_names(that)',
169170
refId,
171+
qryType: 0,
170172
});
171173
});
172174

173-
test('Calls onChange for label_names, label_values, metrics, and query result queries', async () => {
175+
test('Calls onChange for label_names, label_values, metrics, query result and and classic query.', async () => {
174176
const onChange = jest.fn();
175177

176178
props.query = {
@@ -184,8 +186,9 @@ describe('PromVariableQueryEditor', () => {
184186
await selectOptionInTest(screen.getByLabelText('Query type'), 'Label values');
185187
await selectOptionInTest(screen.getByLabelText('Query type'), 'Metrics');
186188
await selectOptionInTest(screen.getByLabelText('Query type'), 'Query result');
189+
await selectOptionInTest(screen.getByLabelText('Query type'), 'Classic query');
187190

188-
expect(onChange).toHaveBeenCalledTimes(4);
191+
expect(onChange).toHaveBeenCalledTimes(5);
189192
});
190193

191194
test('Does not call onChange for series query', async () => {
@@ -220,6 +223,7 @@ describe('PromVariableQueryEditor', () => {
220223
expect(onChange).toHaveBeenCalledWith({
221224
query: 'metrics(a)',
222225
refId,
226+
qryType: 2,
223227
})
224228
);
225229
});
@@ -230,6 +234,7 @@ describe('PromVariableQueryEditor', () => {
230234
props.query = {
231235
refId: 'test',
232236
query: 'label_names()',
237+
qryType: 0,
233238
};
234239

235240
render(<PromVariableQueryEditor {...props} onChange={onChange} />);
@@ -243,6 +248,7 @@ describe('PromVariableQueryEditor', () => {
243248
expect(onChange).toHaveBeenCalledWith({
244249
query: 'label_values(this)',
245250
refId,
251+
qryType: 1,
246252
})
247253
);
248254
});
@@ -270,6 +276,7 @@ describe('PromVariableQueryEditor', () => {
270276
expect(onChange).toHaveBeenCalledWith({
271277
query: 'label_values(that,this)',
272278
refId,
279+
qryType: 1,
273280
})
274281
);
275282
});
@@ -292,6 +299,7 @@ describe('PromVariableQueryEditor', () => {
292299
expect(onChange).toHaveBeenCalledWith({
293300
query: 'query_result(a)',
294301
refId,
302+
qryType: 3,
295303
});
296304
});
297305

@@ -313,6 +321,30 @@ describe('PromVariableQueryEditor', () => {
313321
expect(onChange).toHaveBeenCalledWith({
314322
query: '{a: "example"}',
315323
refId,
324+
qryType: 4,
325+
});
326+
});
327+
328+
test('Calls onChange for classic query onBlur', async () => {
329+
const onChange = jest.fn();
330+
331+
props.query = {
332+
refId: 'test',
333+
qryType: 5,
334+
query: 'label_values(instance)',
335+
};
336+
337+
render(<PromVariableQueryEditor {...props} onChange={onChange} />);
338+
339+
const labelSelect = screen.getByLabelText('Classic Query');
340+
await userEvent.click(labelSelect);
341+
const functionSelect = screen.getByLabelText('Query type').parentElement!;
342+
await userEvent.click(functionSelect);
343+
344+
expect(onChange).toHaveBeenCalledWith({
345+
query: 'label_values(instance)',
346+
refId,
347+
qryType: 5,
316348
});
317349
});
318350
});

public/app/plugins/datasource/prometheus/components/VariableQueryEditor.tsx

+57-11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const variableOptions = [
2626
{ label: 'Metrics', value: QueryType.MetricNames },
2727
{ label: 'Query result', value: QueryType.VarQueryResult },
2828
{ label: 'Series query', value: QueryType.SeriesQuery },
29+
{ label: 'Classic query', value: QueryType.ClassicQuery },
2930
];
3031

3132
export type Props = QueryEditorProps<PrometheusDatasource, PromQuery, PromOptions, PromVariableQuery>;
@@ -49,6 +50,9 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource }: Props)
4950
// seriesQuery is only a whole
5051
const [seriesQuery, setSeriesQuery] = useState('');
5152

53+
// the original variable query implementation
54+
const [classicQuery, setClassicQuery] = useState('');
55+
5256
// list of label names for label_values(), /api/v1/labels, contains the same results as label_names() function
5357
const [labelOptions, setLabelOptions] = useState<Array<SelectableValue<string>>>([]);
5458

@@ -59,17 +63,24 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource }: Props)
5963
if (!query) {
6064
return;
6165
}
62-
// 1. Changing from standard to custom variable editor changes the string attr from expr to query
63-
// 2. jsonnet grafana as code passes a variable as a string
64-
const variableQuery = variableMigration(query);
65-
66-
setLabelNamesMatch(variableQuery.match ?? '');
67-
setQryType(variableQuery.qryType);
68-
setLabel(variableQuery.label ?? '');
69-
setMetric(variableQuery.metric ?? '');
70-
setLabelFilters(variableQuery.labelFilters ?? []);
71-
setVarQuery(variableQuery.varQuery ?? '');
72-
setSeriesQuery(variableQuery.seriesQuery ?? '');
66+
67+
if (query.qryType === QueryType.ClassicQuery) {
68+
setQryType(query.qryType);
69+
setClassicQuery(query.query ?? '');
70+
} else {
71+
// 1. Changing from standard to custom variable editor changes the string attr from expr to query
72+
// 2. jsonnet grafana as code passes a variable as a string
73+
const variableQuery = variableMigration(query);
74+
75+
setLabelNamesMatch(variableQuery.match ?? '');
76+
setQryType(variableQuery.qryType);
77+
setLabel(variableQuery.label ?? '');
78+
setMetric(variableQuery.metric ?? '');
79+
setLabelFilters(variableQuery.labelFilters ?? []);
80+
setVarQuery(variableQuery.varQuery ?? '');
81+
setSeriesQuery(variableQuery.seriesQuery ?? '');
82+
setClassicQuery(variableQuery.classicQuery ?? '');
83+
}
7384
}, [query]);
7485

7586
// set the label names options for the label values var query
@@ -116,6 +127,7 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource }: Props)
116127
match: labelNamesMatch,
117128
varQuery,
118129
seriesQuery,
130+
classicQuery,
119131
refId: 'PrometheusVariableQueryEditor-VariableQuery',
120132
};
121133

@@ -128,6 +140,7 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource }: Props)
128140
// setting query.query property allows for update of variable definition
129141
onChange({
130142
query: queryString,
143+
qryType: updatedVar.qryType,
131144
refId,
132145
});
133146
};
@@ -200,6 +213,10 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource }: Props)
200213
setSeriesQuery(e.currentTarget.value);
201214
};
202215

216+
const onClassicQueryChange = (e: FormEvent<HTMLInputElement>) => {
217+
setClassicQuery(e.currentTarget.value);
218+
};
219+
203220
const promVisualQuery = useCallback(() => {
204221
return { metric: metric, labels: labelFilters, operations: [] };
205222
}, [metric, labelFilters]);
@@ -371,6 +388,35 @@ export const PromVariableQueryEditor = ({ onChange, query, datasource }: Props)
371388
</InlineField>
372389
</InlineFieldRow>
373390
)}
391+
392+
{qryType === QueryType.ClassicQuery && (
393+
<InlineFieldRow>
394+
<InlineField
395+
label="Classic Query"
396+
labelWidth={20}
397+
tooltip={
398+
<div>
399+
The original implemetation of the Prometheus variable query editor. Enter a string with the correct
400+
query type and parameters as described in these docs. For example, label_values(label, metric).
401+
</div>
402+
}
403+
>
404+
<Input
405+
type="text"
406+
aria-label="Classic Query"
407+
placeholder="Classic Query"
408+
value={classicQuery}
409+
onChange={onClassicQueryChange}
410+
onBlur={() => {
411+
if (qryType === QueryType.ClassicQuery && classicQuery) {
412+
onChangeWithVariableString({ qryType });
413+
}
414+
}}
415+
width={100}
416+
/>
417+
</InlineField>
418+
</InlineFieldRow>
419+
)}
374420
</>
375421
);
376422
};

public/app/plugins/datasource/prometheus/migrations/variableMigration.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ export function migrateVariableEditorBackToVariableSupport(QueryVariable: PromVa
123123
const varQuery = removeLineBreaks(QueryVariable.varQuery);
124124
return `query_result(${varQuery})`;
125125
case QueryType.SeriesQuery:
126-
return '' + QueryVariable.seriesQuery;
126+
return QueryVariable.seriesQuery ?? '';
127+
case QueryType.ClassicQuery:
128+
return QueryVariable.classicQuery ?? '';
127129
}
128130

129131
return '';

public/app/plugins/datasource/prometheus/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ export enum PromVariableQueryType {
183183
MetricNames,
184184
VarQueryResult,
185185
SeriesQuery,
186+
ClassicQuery,
186187
}
187188

188189
export interface PromVariableQuery extends DataQuery {
@@ -195,6 +196,7 @@ export interface PromVariableQuery extends DataQuery {
195196
seriesQuery?: string;
196197
labelFilters?: QueryBuilderLabelFilter[];
197198
match?: string;
199+
classicQuery?: string;
198200
}
199201

200202
export type StandardPromVariableQuery = {

0 commit comments

Comments
 (0)