From a2fea9af7610a560fe3d82de203bfb01c9ce9254 Mon Sep 17 00:00:00 2001 From: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com> Date: Mon, 8 May 2023 13:40:50 -0500 Subject: [PATCH] [v9.4.x] Prometheus: bug in creating autocomplete queries with labels (#68031) * Prometheus: bug in creating autocomplete queries with labels (#68003) (cherry picked from commit a1bc1bd36855f1ad37dc5aba82984de890645c5a) --- .../components/MetricSelect.test.tsx | 39 ++++++++++++++++++- .../querybuilder/components/MetricSelect.tsx | 35 ++++++++--------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx index e76a6fecc54..8ba7c27bac4 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.test.tsx @@ -7,7 +7,7 @@ import { DataSourceInstanceSettings, MetricFindValue } from '@grafana/data/src'; import { PrometheusDatasource } from '../../datasource'; import { PromOptions } from '../../types'; -import { MetricSelect } from './MetricSelect'; +import { formatPrometheusLabelFilters, formatPrometheusLabelFiltersToString, MetricSelect } from './MetricSelect'; const instanceSettings = { url: 'proxied', @@ -129,6 +129,43 @@ describe('MetricSelect', () => { await userEvent.type(input, 'new'); await waitFor(() => expect(document.querySelector('mark')).not.toBeInTheDocument()); }); + + it('label filters properly join', () => { + const query = formatPrometheusLabelFilters([ + { + value: 'value', + label: 'label', + op: '=', + }, + { + value: 'value2', + label: 'label2', + op: '=', + }, + ]); + query.forEach((label) => { + expect(label.includes(',', 0)); + }); + }); + it('label filter creation', () => { + const labels = [ + { + value: 'value', + label: 'label', + op: '=', + }, + { + value: 'value2', + label: 'label2', + op: '=', + }, + ]; + + const queryString = formatPrometheusLabelFiltersToString('query', labels); + queryString.split(',').forEach((queryChunk) => { + expect(queryChunk.length).toBeGreaterThan(1); // must be longer then ',' + }); + }); }); async function openMetricSelect() { diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx index 43fe9936bb8..5bda5e63920 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx @@ -65,24 +65,6 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels [styles.highlight] ); - const formatLabelFilters = (labelsFilters: QueryBuilderLabelFilter[]): string[] => { - return labelsFilters.map((label) => { - return `,${label.label}="${label.value}"`; - }); - }; - - /** - * Transform queryString and any currently set label filters into label_values() string - */ - const queryAndFilterToLabelValuesString = ( - queryString: string, - labelsFilters: QueryBuilderLabelFilter[] | undefined - ): string => { - return `label_values({__name__=~".*${queryString}"${ - labelsFilters ? formatLabelFilters(labelsFilters).join() : '' - }},__name__)`; - }; - /** * Reformat the query string and label filters to return all valid results for current query editor state */ @@ -92,7 +74,7 @@ export function MetricSelect({ datasource, query, onChange, onGetMetrics, labels ): string => { const queryString = regexifyLabelValuesQueryString(query); - return queryAndFilterToLabelValuesString(queryString, labelsFilters); + return formatPrometheusLabelFiltersToString(queryString, labelsFilters); }; /** @@ -161,3 +143,18 @@ const getStyles = (theme: GrafanaTheme2) => ({ background-color: ${theme.colors.warning.main}; `, }); + +export const formatPrometheusLabelFiltersToString = ( + queryString: string, + labelsFilters: QueryBuilderLabelFilter[] | undefined +): string => { + const filterArray = labelsFilters ? formatPrometheusLabelFilters(labelsFilters) : []; + + return `label_values({__name__=~".*${queryString}"${filterArray ? filterArray.join('') : ''}},__name__)`; +}; + +export const formatPrometheusLabelFilters = (labelsFilters: QueryBuilderLabelFilter[]): string[] => { + return labelsFilters.map((label) => { + return `,${label.label}="${label.value}"`; + }); +};