Alerting: Support filtering rules by multiple datasources (#64355)

* Support having a datasources array in the rules filter

* Fix tests

* Display a MultiplePicker for filtering datasources

* Fix tests

* Refactor as MultipleDataSourcePicker as FC

* Make select box wider

* Remove FC from component definition

* Display ds options in groups based on whether they manage/don't manage rules

* Change dropdown texts and add help info
This commit is contained in:
Virginia Cepeda
2023-03-22 12:02:56 -03:00
committed by GitHub
parent b3d0c39f08
commit 43bbe567e7
8 changed files with 258 additions and 31 deletions

View File

@@ -7,7 +7,7 @@ describe('Alert rules searchParser', () => {
describe('getSearchFilterFromQuery', () => {
it.each(['datasource:prometheus'])('should parse data source filter from "%s" query', (query) => {
const filter = getSearchFilterFromQuery(query);
expect(filter.dataSourceName).toBe('prometheus');
expect(filter.dataSourceNames).toEqual(['prometheus']);
});
it.each(['namespace:integrations-node'])('should parse namespace filter from "%s" query', (query) => {
@@ -79,7 +79,7 @@ describe('Alert rules searchParser', () => {
'datasource:"prom dev" namespace:"node one" label:"team=frontend us" group:"cpu alerts" rule:"cpu failure"';
const filter = getSearchFilterFromQuery(query);
expect(filter.dataSourceName).toBe('prom dev');
expect(filter.dataSourceNames).toEqual(['prom dev']);
expect(filter.namespace).toBe('node one');
expect(filter.labels).toContain('team=frontend us');
expect(filter.groupName).toContain('cpu alerts');
@@ -91,7 +91,7 @@ describe('Alert rules searchParser', () => {
'datasource:prom::dev/linux>>; namespace:"[{node}] (#20+)" label:_region=apac|emea\\nasa group:$20.00%$ rule:"cpu!! & memory.,?"';
const filter = getSearchFilterFromQuery(query);
expect(filter.dataSourceName).toBe('prom::dev/linux>>;');
expect(filter.dataSourceNames).toEqual(['prom::dev/linux>>;']);
expect(filter.namespace).toBe('[{node}] (#20+)');
expect(filter.labels).toContain('_region=apac|emea\\nasa');
expect(filter.groupName).toContain('$20.00%$');
@@ -110,7 +110,7 @@ describe('Alert rules searchParser', () => {
const query = 'datasource:prometheus utilization label:team cpu';
const filter = getSearchFilterFromQuery(query);
expect(filter.dataSourceName).toBe('prometheus');
expect(filter.dataSourceNames).toEqual(['prometheus']);
expect(filter.labels).toContain('team');
expect(filter.freeFormWords).toContain('utilization');
expect(filter.freeFormWords).toContain('cpu');
@@ -130,7 +130,7 @@ describe('Alert rules searchParser', () => {
it('should apply filters to an empty query', () => {
const filter = getFilter({
freeFormWords: ['cpu', 'eighty'],
dataSourceName: 'Mimir Dev',
dataSourceNames: ['Mimir Dev'],
namespace: '/etc/prometheus',
labels: ['team', 'region=apac'],
groupName: 'cpu-usage',
@@ -149,7 +149,7 @@ describe('Alert rules searchParser', () => {
it('should update filters in existing query', () => {
const filter = getFilter({
dataSourceName: 'Mimir Dev',
dataSourceNames: ['Mimir Dev'],
namespace: '/etc/prometheus',
labels: ['team', 'region=apac'],
groupName: 'cpu-usage',
@@ -166,7 +166,7 @@ describe('Alert rules searchParser', () => {
it('should preserve the order of parameters when updating', () => {
const filter = getFilter({
dataSourceName: 'Mimir Dev',
dataSourceNames: ['Mimir Dev'],
namespace: '/etc/prometheus',
labels: ['region=emea'],
groupName: 'cpu-usage',

View File

@@ -17,7 +17,7 @@ export interface RulesFilter {
ruleName?: string;
ruleState?: PromAlertingRuleState;
ruleType?: PromRuleType;
dataSourceName?: string;
dataSourceNames: string[];
labels: string[];
ruleHealth?: RuleHealth;
}
@@ -42,10 +42,10 @@ export enum RuleHealth {
// Define how to map parsed tokens into the filter object
export function getSearchFilterFromQuery(query: string): RulesFilter {
const filter: RulesFilter = { labels: [], freeFormWords: [] };
const filter: RulesFilter = { labels: [], freeFormWords: [], dataSourceNames: [] };
const tokenToFilterMap: QueryFilterMapper = {
[terms.DataSourceToken]: (value) => (filter.dataSourceName = value),
[terms.DataSourceToken]: (value) => filter.dataSourceNames.push(value),
[terms.NameSpaceToken]: (value) => (filter.namespace = value),
[terms.GroupToken]: (value) => (filter.groupName = value),
[terms.RuleToken]: (value) => (filter.ruleName = value),
@@ -68,8 +68,8 @@ export function applySearchFilterToQuery(query: string, filter: RulesFilter): st
// Convert filter object into an array
// It allows to pick filters from the array in the same order as they were applied in the original query
if (filter.dataSourceName) {
filterStateArray.push({ type: terms.DataSourceToken, value: filter.dataSourceName });
if (filter.dataSourceNames) {
filterStateArray.push(...filter.dataSourceNames.map((t) => ({ type: terms.DataSourceToken, value: t })));
}
if (filter.namespace) {
filterStateArray.push({ type: terms.NameSpaceToken, value: filter.namespace });