diff --git a/public/app/plugins/datasource/prometheus/datasource.ts b/public/app/plugins/datasource/prometheus/datasource.ts index 8514b6ca7d4..0cedafdff75 100644 --- a/public/app/plugins/datasource/prometheus/datasource.ts +++ b/public/app/plugins/datasource/prometheus/datasource.ts @@ -10,6 +10,7 @@ import { BackendSrv } from 'app/core/services/backend_srv'; import addLabelToQuery from './add_label_to_query'; import { getQueryHints } from './query_hints'; +import { expandRecordingRules } from './language_utils'; export function alignRange(start, end, step) { const alignedEnd = Math.ceil(end / step) * step; @@ -468,11 +469,8 @@ export class PrometheusDatasource { return `sum(${query.trim()}) by ($1)`; } case 'EXPAND_RULES': { - const mapping = action.mapping; - if (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]); + if (action.mapping) { + return expandRecordingRules(query, action.mapping); } } default: diff --git a/public/app/plugins/datasource/prometheus/language_utils.ts b/public/app/plugins/datasource/prometheus/language_utils.ts index 5995c427cd1..00cce0195af 100644 --- a/public/app/plugins/datasource/prometheus/language_utils.ts +++ b/public/app/plugins/datasource/prometheus/language_utils.ts @@ -83,3 +83,9 @@ export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any 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}`); +} diff --git a/public/app/plugins/datasource/prometheus/specs/language_utils.test.ts b/public/app/plugins/datasource/prometheus/specs/language_utils.test.ts index 748217e21b7..b33c0094700 100644 --- a/public/app/plugins/datasource/prometheus/specs/language_utils.test.ts +++ b/public/app/plugins/datasource/prometheus/specs/language_utils.test.ts @@ -1,4 +1,4 @@ -import { parseSelector } from '../language_utils'; +import { expandRecordingRules, parseSelector } from '../language_utils'; describe('parseSelector()', () => { let parsed; @@ -62,3 +62,25 @@ describe('parseSelector()', () => { 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'); + }); +});