mirror of https://github.com/grafana/grafana
Alerting: Fix the silence url's matcher parameters (#43898)
* Split silence matchers parameter into a separate entry for each label * Unify the silence link creation * Remove duplicated matchers when parsing to/from query params * Add tests for matchers * Add a comment with a duplication removal explanation * Improve label duplication comment * Remove redundant code * Use uniqBy to simplify the code. Rename matchers parameter * Fix Silence test datapull/43974/head^2
parent
8f1468df6a
commit
c829535f14
@ -0,0 +1,8 @@ |
||||
import { useMemo } from 'react'; |
||||
import { useLocation } from 'react-router-dom'; |
||||
|
||||
export function useURLSearchParams(): [URLSearchParams] { |
||||
const { search } = useLocation(); |
||||
const queryParams = useMemo(() => new URLSearchParams(search), [search]); |
||||
return [queryParams]; |
||||
} |
@ -0,0 +1,36 @@ |
||||
import { getMatcherQueryParams, parseQueryParamMatchers } from './matchers'; |
||||
|
||||
describe('Unified Alerting matchers', () => { |
||||
describe('getMatcherQueryParams tests', () => { |
||||
it('Should create an entry for each label', () => { |
||||
const params = getMatcherQueryParams({ foo: 'bar', alertname: 'TestData - No data', rule_uid: 'YNZBpGJnk' }); |
||||
|
||||
const matcherParams = params.getAll('matcher'); |
||||
|
||||
expect(matcherParams).toHaveLength(3); |
||||
expect(matcherParams).toContain('foo=bar'); |
||||
expect(matcherParams).toContain('alertname=TestData - No data'); |
||||
expect(matcherParams).toContain('rule_uid=YNZBpGJnk'); |
||||
}); |
||||
}); |
||||
|
||||
describe('parseQueryParamMatchers tests', () => { |
||||
it('Should create a matcher for each unique label-expression pair', () => { |
||||
const matchers = parseQueryParamMatchers(['alertname=TestData 1', 'rule_uid=YNZBpGJnk']); |
||||
|
||||
expect(matchers).toHaveLength(2); |
||||
expect(matchers[0].name).toBe('alertname'); |
||||
expect(matchers[0].value).toBe('TestData 1'); |
||||
expect(matchers[1].name).toBe('rule_uid'); |
||||
expect(matchers[1].value).toBe('YNZBpGJnk'); |
||||
}); |
||||
|
||||
it('Should create one matcher, using the first occurence when duplicated labels exists', () => { |
||||
const matchers = parseQueryParamMatchers(['alertname=TestData 1', 'alertname=TestData 2']); |
||||
|
||||
expect(matchers).toHaveLength(1); |
||||
expect(matchers[0].name).toBe('alertname'); |
||||
expect(matchers[0].value).toBe('TestData 1'); |
||||
}); |
||||
}); |
||||
}); |
@ -1,22 +1,26 @@ |
||||
import { Matcher } from 'app/plugins/datasource/alertmanager/types'; |
||||
import { Labels } from '@grafana/data'; |
||||
import { parseMatcher } from './alertmanager'; |
||||
import { uniqBy } from 'lodash'; |
||||
|
||||
// parses comma separated matchers like "foo=bar,baz=~bad*" into SilenceMatcher[]
|
||||
export function parseQueryParamMatchers(paramValue: string): Matcher[] { |
||||
return paramValue |
||||
.split(',') |
||||
.filter((x) => !!x.trim()) |
||||
.map((x) => parseMatcher(x.trim())); |
||||
// Parses a list of entries like like "['foo=bar', 'baz=~bad*']" into SilenceMatcher[]
|
||||
export function parseQueryParamMatchers(matcherPairs: string[]): Matcher[] { |
||||
const parsedMatchers = matcherPairs.filter((x) => !!x.trim()).map((x) => parseMatcher(x.trim())); |
||||
|
||||
// Due to migration, old alert rules might have a duplicated alertname label
|
||||
// To handle that case want to filter out duplicates and make sure there are only unique labels
|
||||
return uniqBy(parsedMatchers, (matcher) => matcher.name); |
||||
} |
||||
|
||||
export const getMatcherQueryParams = (labels: Labels) => { |
||||
return `matchers=${encodeURIComponent( |
||||
Object.entries(labels) |
||||
.filter(([labelKey]) => !(labelKey.startsWith('__') && labelKey.endsWith('__'))) |
||||
.map(([labelKey, labelValue]) => { |
||||
return `${labelKey}=${labelValue}`; |
||||
}) |
||||
.join(',') |
||||
)}`;
|
||||
const validMatcherLabels = Object.entries(labels).filter( |
||||
([labelKey]) => !(labelKey.startsWith('__') && labelKey.endsWith('__')) |
||||
); |
||||
|
||||
const matcherUrlParams = new URLSearchParams(); |
||||
validMatcherLabels.forEach(([labelKey, labelValue]) => |
||||
matcherUrlParams.append('matcher', `${labelKey}=${labelValue}`) |
||||
); |
||||
|
||||
return matcherUrlParams; |
||||
}; |
||||
|
Loading…
Reference in new issue