mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Variables: Fixes missing empty elements from regex filters (#31156)
* Variables: Fixes missing empty elements from regex filters * Chore: cleanup comment * Chore: removes unused import
This commit is contained in:
parent
b3c32277dd
commit
39993a6884
@ -1,6 +1,6 @@
|
||||
import { reducerTester } from '../../../../test/core/redux/reducerTester';
|
||||
import {
|
||||
getAllMatches,
|
||||
metricNamesToVariableValues,
|
||||
queryVariableReducer,
|
||||
sortVariableValues,
|
||||
updateVariableOptions,
|
||||
@ -12,7 +12,7 @@ import { VariablesState } from '../state/variablesReducer';
|
||||
import { getVariableTestContext } from '../state/helpers';
|
||||
import { toVariablePayload } from '../state/types';
|
||||
import { createQueryVariableAdapter } from './adapter';
|
||||
import { MetricFindValue, stringToJsRegex } from '@grafana/data';
|
||||
import { MetricFindValue } from '@grafana/data';
|
||||
|
||||
describe('queryVariableReducer', () => {
|
||||
const adapter = createQueryVariableAdapter();
|
||||
@ -307,37 +307,79 @@ describe('sortVariableValues', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllMatches', () => {
|
||||
it.each`
|
||||
str | regex | expected
|
||||
${'A{somelabel="atext",somevalue="avalue"}'} | ${'/unknown/gi'} | ${{}}
|
||||
${'A{somelabel="atext",somevalue="avalue"}'} | ${'/unknown/i'} | ${{}}
|
||||
${'A{somelabel="atext",somevalue="avalue"}'} | ${'/some(\\w+)/gi'} | ${{ 0: 'somevalue', 1: 'value', index: 20, input: 'A{somelabel="atext",somevalue="avalue"}' }}
|
||||
${'A{somelabel="atext",somevalue="avalue"}'} | ${'/some(\\w+)/i'} | ${{ 0: 'somelabel', 1: 'label', index: 2, input: 'A{somelabel="atext",somevalue="avalue"}' }}
|
||||
${'A{somelabel="atext",somevalue="avalue"}'} | ${'/somevalue="(?<value>[^"]+)|somelabel="(?<text>[^"]+)/gi'} | ${{
|
||||
0: 'somevalue="avalue',
|
||||
1: 'avalue',
|
||||
2: 'atext',
|
||||
groups: {
|
||||
text: 'atext',
|
||||
value: 'avalue',
|
||||
},
|
||||
index: 20,
|
||||
input: 'A{somelabel="atext",somevalue="avalue"}',
|
||||
}}
|
||||
${'A{somelabel="atext",somevalue="avalue"}'} | ${'/somevalue="(?<value>[^"]+)|somelabel="(?<text>[^"]+)/i'} | ${{
|
||||
0: 'somelabel="atext',
|
||||
1: undefined,
|
||||
2: 'atext',
|
||||
groups: {
|
||||
text: 'atext',
|
||||
},
|
||||
index: 2,
|
||||
input: 'A{somelabel="atext",somevalue="avalue"}',
|
||||
}}
|
||||
`('when called with str:{$str}, regex:{$regex} then it should return correct matches', ({ str, regex, expected }) => {
|
||||
const result = getAllMatches(str, stringToJsRegex(regex));
|
||||
describe('metricNamesToVariableValues', () => {
|
||||
const item = (str: string) => ({ text: str, value: str, selected: false });
|
||||
const metricsNames = [
|
||||
item('go_info{instance="demo.robustperception.io:9090",job="prometheus",version="go1.15.6"} 1 1613047998000'),
|
||||
item('go_info{instance="demo.robustperception.io:9091",job="pushgateway",version="go1.15.6"} 1 1613047998000'),
|
||||
item('go_info{instance="demo.robustperception.io:9093",job="alertmanager",version="go1.14.4"} 1 1613047998000'),
|
||||
item('go_info{instance="demo.robustperception.io:9100",job="node",version="go1.14.4"} 1 1613047998000'),
|
||||
];
|
||||
|
||||
const expected1 = [
|
||||
{ value: 'demo.robustperception.io:9090', text: 'demo.robustperception.io:9090', selected: false },
|
||||
{ value: 'demo.robustperception.io:9091', text: 'demo.robustperception.io:9091', selected: false },
|
||||
{ value: 'demo.robustperception.io:9093', text: 'demo.robustperception.io:9093', selected: false },
|
||||
{ value: 'demo.robustperception.io:9100', text: 'demo.robustperception.io:9100', selected: false },
|
||||
];
|
||||
|
||||
const expected2 = [
|
||||
{ value: 'prometheus', text: 'prometheus', selected: false },
|
||||
{ value: 'pushgateway', text: 'pushgateway', selected: false },
|
||||
{ value: 'alertmanager', text: 'alertmanager', selected: false },
|
||||
{ value: 'node', text: 'node', selected: false },
|
||||
];
|
||||
|
||||
const expected3 = [
|
||||
{ value: 'demo.robustperception.io:9090', text: 'prometheus', selected: false },
|
||||
{ value: 'demo.robustperception.io:9091', text: 'pushgateway', selected: false },
|
||||
{ value: 'demo.robustperception.io:9093', text: 'alertmanager', selected: false },
|
||||
{ value: 'demo.robustperception.io:9100', text: 'node', selected: false },
|
||||
];
|
||||
|
||||
const expected4 = [
|
||||
{ value: 'demo.robustperception.io:9090', text: 'demo.robustperception.io:9090', selected: false },
|
||||
{ value: undefined, text: undefined, selected: false },
|
||||
{ value: 'demo.robustperception.io:9091', text: 'demo.robustperception.io:9091', selected: false },
|
||||
{ value: 'demo.robustperception.io:9093', text: 'demo.robustperception.io:9093', selected: false },
|
||||
{ value: 'demo.robustperception.io:9100', text: 'demo.robustperception.io:9100', selected: false },
|
||||
];
|
||||
|
||||
it.each`
|
||||
variableRegEx | expected
|
||||
${''} | ${metricsNames}
|
||||
${'/unknown/'} | ${[]}
|
||||
${'/unknown/g'} | ${[]}
|
||||
${'/go/'} | ${metricsNames}
|
||||
${'/go/g'} | ${metricsNames}
|
||||
${'/(go)/'} | ${[{ value: 'go', text: 'go', selected: false }]}
|
||||
${'/(go)/g'} | ${[{ value: 'go', text: 'go', selected: false }]}
|
||||
${'/(go)?/'} | ${[{ value: 'go', text: 'go', selected: false }]}
|
||||
${'/(go)?/g'} | ${[{ value: 'go', text: 'go', selected: false }, { value: undefined, text: undefined, selected: false }]}
|
||||
${'/go(\\w+)/'} | ${[{ value: '_info', text: '_info', selected: false }]}
|
||||
${'/go(\\w+)/g'} | ${[{ value: '_info', text: '_info', selected: false }, { value: '1', text: '1', selected: false }]}
|
||||
${'/.*_(\\w+)\\{/'} | ${[{ value: 'info', text: 'info', selected: false }]}
|
||||
${'/.*_(\\w+)\\{/g'} | ${[{ value: 'info', text: 'info', selected: false }]}
|
||||
${'/instance="(?<value>[^"]+)/'} | ${expected1}
|
||||
${'/instance="(?<value>[^"]+)/g'} | ${expected1}
|
||||
${'/instance="(?<grp1>[^"]+)/'} | ${expected1}
|
||||
${'/instance="(?<grp1>[^"]+)/g'} | ${expected1}
|
||||
${'/instancee="(?<value>[^"]+)/'} | ${[]}
|
||||
${'/job="(?<text>[^"]+)/'} | ${expected2}
|
||||
${'/job="(?<text>[^"]+)/g'} | ${expected2}
|
||||
${'/job="(?<grp2>[^"]+)/'} | ${expected2}
|
||||
${'/job="(?<grp2>[^"]+)/g'} | ${expected2}
|
||||
${'/jobb="(?<text>[^"]+)/g'} | ${[]}
|
||||
${'/instance="(?<value>[^"]+)|job="(?<text>[^"]+)/'} | ${expected1}
|
||||
${'/instance="(?<value>[^"]+)|job="(?<text>[^"]+)/g'} | ${expected3}
|
||||
${'/instance="(?<grp1>[^"]+)|job="(?<grp2>[^"]+)/'} | ${expected1}
|
||||
${'/instance="(?<grp1>[^"]+)|job="(?<grp2>[^"]+)/g'} | ${expected4}
|
||||
${'/instance="(?<value>[^"]+).*job="(?<text>[^"]+)/'} | ${expected3}
|
||||
${'/instance="(?<value>[^"]+).*job="(?<text>[^"]+)/g'} | ${expected3}
|
||||
${'/instance="(?<grp1>[^"]+).*job="(?<grp2>[^"]+)/'} | ${expected1}
|
||||
${'/instance="(?<grp1>[^"]+).*job="(?<grp2>[^"]+)/g'} | ${expected1}
|
||||
`('when called with variableRegEx:$variableRegEx then it return correct options', ({ variableRegEx, expected }) => {
|
||||
const result = metricNamesToVariableValues(variableRegEx, VariableSort.disabled, metricsNames);
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
@ -88,30 +88,33 @@ export const sortVariableValues = (options: any[], sortOrder: VariableSort) => {
|
||||
return options;
|
||||
};
|
||||
|
||||
export const getAllMatches = (str: string, regex: RegExp): any => {
|
||||
const results = {};
|
||||
let matches;
|
||||
const getAllMatches = (str: string, regex: RegExp): RegExpExecArray[] => {
|
||||
const results: RegExpExecArray[] = [];
|
||||
let matches = null;
|
||||
|
||||
regex.lastIndex = 0;
|
||||
|
||||
do {
|
||||
matches = regex.exec(str);
|
||||
_.merge(results, matches);
|
||||
} while (regex.global && matches);
|
||||
if (matches) {
|
||||
results.push(matches);
|
||||
}
|
||||
} while (regex.global && matches && matches[0] !== '' && matches[0] !== undefined);
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
const metricNamesToVariableValues = (variableRegEx: string, sort: VariableSort, metricNames: any[]) => {
|
||||
let regex, i, matches;
|
||||
export const metricNamesToVariableValues = (variableRegEx: string, sort: VariableSort, metricNames: any[]) => {
|
||||
let regex;
|
||||
let options: VariableOption[] = [];
|
||||
|
||||
if (variableRegEx) {
|
||||
regex = stringToJsRegex(variableRegEx);
|
||||
}
|
||||
|
||||
for (i = 0; i < metricNames.length; i++) {
|
||||
for (let i = 0; i < metricNames.length; i++) {
|
||||
const item = metricNames[i];
|
||||
let text = item.text === undefined || item.text === null ? item.value : item.text;
|
||||
|
||||
let value = item.value === undefined || item.value === null ? item.text : item.value;
|
||||
|
||||
if (_.isNumber(value)) {
|
||||
@ -123,24 +126,28 @@ const metricNamesToVariableValues = (variableRegEx: string, sort: VariableSort,
|
||||
}
|
||||
|
||||
if (regex) {
|
||||
matches = getAllMatches(value, regex);
|
||||
|
||||
if (_.isEmpty(matches)) {
|
||||
const matches = getAllMatches(value, regex);
|
||||
if (!matches.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matches.groups && matches.groups.value && matches.groups.text) {
|
||||
value = matches.groups.value;
|
||||
text = matches.groups.text;
|
||||
} else if (matches.groups && matches.groups.value) {
|
||||
value = matches.groups.value;
|
||||
text = value;
|
||||
} else if (matches.groups && matches.groups.text) {
|
||||
text = matches.groups.text;
|
||||
value = text;
|
||||
} else if (matches['1']) {
|
||||
text = matches['1'];
|
||||
value = matches['1'];
|
||||
const valueGroup = matches.find((m) => m.groups && m.groups.value);
|
||||
const textGroup = matches.find((m) => m.groups && m.groups.text);
|
||||
const firstMatch = matches.find((m) => m.length > 1);
|
||||
const manyMatches = matches.length > 1 && firstMatch;
|
||||
|
||||
if (valueGroup || textGroup) {
|
||||
value = valueGroup?.groups?.value ?? textGroup?.groups?.text;
|
||||
text = textGroup?.groups?.text ?? valueGroup?.groups?.value;
|
||||
} else if (manyMatches) {
|
||||
for (let j = 0; j < matches.length; j++) {
|
||||
const match = matches[j];
|
||||
options.push({ text: match[1], value: match[1], selected: false });
|
||||
}
|
||||
continue;
|
||||
} else if (firstMatch) {
|
||||
text = firstMatch[1];
|
||||
value = firstMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user