diff --git a/packages/grafana-prometheus/src/utf8_support.test.ts b/packages/grafana-prometheus/src/utf8_support.test.ts index 5b02d3920e3..4ee3af057ef 100644 --- a/packages/grafana-prometheus/src/utf8_support.test.ts +++ b/packages/grafana-prometheus/src/utf8_support.test.ts @@ -124,4 +124,31 @@ describe('wrapUtf8Filters', () => { const expected = 'key1="nested \\"escaped\\" quotes",key2="value with \\"escaped\\" quotes"'; expect(result).toEqual(expected); }); + + it('should handle different Prometheus operators correctly', () => { + const inputs = [ + 'label="value"', // equals + 'label!="different value"', // not equals + 'label=~"regex.*value"', // regex match + 'label!~"not.regex.*value"', // regex not match + 'utf8.label.spaß!="no match"', // utf8 with not equals + 'utf8.label.spaß=~"match.*"', // utf8 with regex match + 'complex case=~".*",simple="value"', // multiple operators + ]; + + const expected = [ + 'label="value"', + 'label!="different value"', + 'label=~"regex.*value"', + 'label!~"not.regex.*value"', + '"utf8.label.spaß"!="no match"', + '"utf8.label.spaß"=~"match.*"', + '"complex case"=~".*",simple="value"', + ]; + + inputs.forEach((input, index) => { + const result = wrapUtf8Filters(input); + expect(result).toEqual(expected[index]); + }); + }); }); diff --git a/packages/grafana-prometheus/src/utf8_support.ts b/packages/grafana-prometheus/src/utf8_support.ts index 9f757c0bc73..a9ce776364b 100644 --- a/packages/grafana-prometheus/src/utf8_support.ts +++ b/packages/grafana-prometheus/src/utf8_support.ts @@ -82,10 +82,19 @@ const isValidCodePoint = (codePoint: number): boolean => { export const wrapUtf8Filters = (filterStr: string): string => { const resultArray: string[] = []; + const operatorRegex = /(=~|!=|!~|=)/; // NOTE: the order of the operators is important here let currentKey = ''; let currentValue = ''; let inQuotes = false; let temp = ''; + const addResult = () => { + const operatorMatch = temp.match(operatorRegex); + if (operatorMatch) { + const operator = operatorMatch[0]; + [currentKey, currentValue] = temp.split(operator); + resultArray.push(`${utf8Support(currentKey.trim())}${operator}"${currentValue.slice(1, -1)}"`); + } + }; for (const char of filterStr) { if (char === '"' && temp[temp.length - 1] !== '\\') { @@ -94,8 +103,7 @@ export const wrapUtf8Filters = (filterStr: string): string => { temp += char; } else if (char === ',' && !inQuotes) { // When outside quotes and encountering ',', finalize the current pair - [currentKey, currentValue] = temp.split('='); - resultArray.push(`${utf8Support(currentKey.trim())}="${currentValue.slice(1, -1)}"`); + addResult(); temp = ''; // Reset for the next pair } else { // Collect characters @@ -105,9 +113,7 @@ export const wrapUtf8Filters = (filterStr: string): string => { // Handle the last key-value pair if (temp) { - [currentKey, currentValue] = temp.split('='); - resultArray.push(`${utf8Support(currentKey.trim())}="${currentValue.slice(1, -1)}"`); + addResult(); } - return resultArray.join(','); };