Commit e3e8be16 by David Kaltschmidt

Prometheus: fix rules expansion

Rules expansion (available via query hints in explore) was broken for expressions that contained selectors.

- fix replacing regexp to recognize `{` and `[` as the end of a rule name
- moved logic to language utils
- added tests
parent ac8731b9
...@@ -10,6 +10,7 @@ import { BackendSrv } from 'app/core/services/backend_srv'; ...@@ -10,6 +10,7 @@ import { BackendSrv } from 'app/core/services/backend_srv';
import addLabelToQuery from './add_label_to_query'; import addLabelToQuery from './add_label_to_query';
import { getQueryHints } from './query_hints'; import { getQueryHints } from './query_hints';
import { expandRecordingRules } from './language_utils';
export function alignRange(start, end, step) { export function alignRange(start, end, step) {
const alignedEnd = Math.ceil(end / step) * step; const alignedEnd = Math.ceil(end / step) * step;
...@@ -468,11 +469,8 @@ export class PrometheusDatasource { ...@@ -468,11 +469,8 @@ export class PrometheusDatasource {
return `sum(${query.trim()}) by ($1)`; return `sum(${query.trim()}) by ($1)`;
} }
case 'EXPAND_RULES': { case 'EXPAND_RULES': {
const mapping = action.mapping; if (action.mapping) {
if (mapping) { return expandRecordingRules(query, action.mapping);
const ruleNames = Object.keys(mapping);
const rulesRegex = new RegExp(`(\\s|^)(${ruleNames.join('|')})(\\s|$|\\()`, 'ig');
return query.replace(rulesRegex, (match, pre, name, post) => mapping[name]);
} }
} }
default: default:
......
...@@ -83,3 +83,9 @@ export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any ...@@ -83,3 +83,9 @@ export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any
return { labelKeys, selector: selectorString }; return { labelKeys, selector: selectorString };
} }
export function expandRecordingRules(query: string, mapping: { [name: string]: string }): string {
const ruleNames = Object.keys(mapping);
const rulesRegex = new RegExp(`(\\s|^)(${ruleNames.join('|')})(\\s|$|\\(|\\[|\\{)`, 'ig');
return query.replace(rulesRegex, (match, pre, name, post) => `${pre}${mapping[name]}${post}`);
}
import { parseSelector } from '../language_utils'; import { expandRecordingRules, parseSelector } from '../language_utils';
describe('parseSelector()', () => { describe('parseSelector()', () => {
let parsed; let parsed;
...@@ -62,3 +62,25 @@ describe('parseSelector()', () => { ...@@ -62,3 +62,25 @@ describe('parseSelector()', () => {
expect(parsed.selector).toBe('{__name__="bar:metric:1m"}'); expect(parsed.selector).toBe('{__name__="bar:metric:1m"}');
}); });
}); });
describe('expandRecordingRules()', () => {
it('returns query w/o recording rules as is', () => {
expect(expandRecordingRules('metric', {})).toBe('metric');
expect(expandRecordingRules('metric + metric', {})).toBe('metric + metric');
expect(expandRecordingRules('metric{}', {})).toBe('metric{}');
});
it('does not modify recording rules name in label values', () => {
expect(expandRecordingRules('{__name__="metric"} + bar', { metric: 'foo', bar: 'super' })).toBe(
'{__name__="metric"} + super'
);
});
it('returns query with expanded recording rules', () => {
expect(expandRecordingRules('metric', { metric: 'foo' })).toBe('foo');
expect(expandRecordingRules('metric + metric', { metric: 'foo' })).toBe('foo + foo');
expect(expandRecordingRules('metric{}', { metric: 'foo' })).toBe('foo{}');
expect(expandRecordingRules('metric[]', { metric: 'foo' })).toBe('foo[]');
expect(expandRecordingRules('metric + foo', { metric: 'foo', foo: 'bar' })).toBe('foo + bar');
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment