From 7045de2aa3a91f41cd64091b7a3cfd27d54f565f Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 8 May 2023 19:14:32 +0100 Subject: [PATCH] [v9.5.x] Prometheus: bug in creating autocomplete queries with labels (#68025) Prometheus: bug in creating autocomplete queries with labels (#68003) Fix bug formatting multiple prometheus labels when doing metric query (cherry picked from commit a1bc1bd36855f1ad37dc5aba82984de890645c5a) Co-authored-by: Galen Kistler <109082771+gtk-grafana@users.noreply.github.com> --- .../components/MetricSelect.test.tsx | 44 ++++++++++++++++++- .../querybuilder/components/MetricSelect.tsx | 35 +++++++-------- 2 files changed, 59 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 63344ad82e5..ade5c9d2c84 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,12 @@ import { DataSourceInstanceSettings, MetricFindValue } from '@grafana/data/src'; import { PrometheusDatasource } from '../../datasource'; import { PromOptions } from '../../types'; -import { MetricSelect, Props } from './MetricSelect'; +import { + formatPrometheusLabelFilters, + formatPrometheusLabelFiltersToString, + MetricSelect, + Props, +} from './MetricSelect'; const instanceSettings = { url: 'proxied', @@ -130,6 +135,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 74c48ef49cc..3a6f126ea19 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricSelect.tsx @@ -73,24 +73,6 @@ export function MetricSelect({ [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 */ @@ -100,7 +82,7 @@ export function MetricSelect({ ): string => { const queryString = regexifyLabelValuesQueryString(query); - return queryAndFilterToLabelValuesString(queryString, labelsFilters); + return formatPrometheusLabelFiltersToString(queryString, labelsFilters); }; /** @@ -178,3 +160,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}"`; + }); +};