diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 25eaaf0f6eb..38bd744a987 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -117,6 +117,7 @@ Experimental features might be changed or removed without prior notice. | `pluginsDynamicAngularDetectionPatterns` | Enables fetching Angular detection patterns for plugins from GCOM and fallback to hardcoded ones | | `alertingLokiRangeToInstant` | Rewrites eligible loki range queries to instant queries | | `flameGraphV2` | New version of flame graph with new features | +| `elasticToggleableFilters` | Enable support to toggle filters off from the query through the Logs Details component | ## Development feature toggles diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index c61b7101bb2..e1aec15f4d8 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -104,4 +104,5 @@ export interface FeatureToggles { pluginsDynamicAngularDetectionPatterns?: boolean; alertingLokiRangeToInstant?: boolean; flameGraphV2?: boolean; + elasticToggleableFilters?: boolean; } diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index ed69595d67c..3272ccb4846 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -586,5 +586,12 @@ var ( Stage: FeatureStageExperimental, Owner: grafanaObservabilityTracesAndProfilingSquad, }, + { + Name: "elasticToggleableFilters", + Description: "Enable support to toggle filters off from the query through the Logs Details component", + Stage: FeatureStageExperimental, + FrontendOnly: true, + Owner: grafanaObservabilityLogsSquad, + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 60d826b5cd3..6c6ef4611a2 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -85,3 +85,4 @@ recordedQueriesMulti,experimental,@grafana/observability-metrics,false,false,fal pluginsDynamicAngularDetectionPatterns,experimental,@grafana/plugins-platform-backend,false,false,false,false alertingLokiRangeToInstant,experimental,@grafana/alerting-squad,false,false,false,false flameGraphV2,experimental,@grafana/observability-traces-and-profiling,false,false,false,true +elasticToggleableFilters,experimental,@grafana/observability-logs,false,false,false,true diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index f818170de89..ef23d271b3a 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -350,4 +350,8 @@ const ( // FlagFlameGraphV2 // New version of flame graph with new features FlagFlameGraphV2 = "flameGraphV2" + + // FlagElasticToggleableFilters + // Enable support to toggle filters off from the query through the Logs Details component + FlagElasticToggleableFilters = "elasticToggleableFilters" ) diff --git a/public/app/plugins/datasource/elasticsearch/datasource.test.ts b/public/app/plugins/datasource/elasticsearch/datasource.test.ts index 408fd425dc3..603aaab2b2c 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.test.ts +++ b/public/app/plugins/datasource/elasticsearch/datasource.test.ts @@ -1185,6 +1185,7 @@ describe('modifyQuery', () => { let ds: ElasticDatasource; beforeEach(() => { ds = getTestContext().ds; + config.featureToggles.elasticToggleableFilters = true; }); describe('with empty query', () => { let query: ElasticsearchQuery; @@ -1243,6 +1244,26 @@ describe('modifyQuery', () => { expect(ds.modifyQuery(query, { type: 'unknown', options: { key: 'foo', value: 'bar' } }).query).toBe(query.query); }); }); + + describe('legacy behavior', () => { + beforeEach(() => { + config.featureToggles.elasticToggleableFilters = false; + }); + it('should not modify other filters in the query', () => { + expect( + ds.modifyQuery( + { query: 'test:"value"', refId: 'A' }, + { type: 'ADD_FILTER', options: { key: 'test', value: 'value' } } + ).query + ).toBe('test:"value"'); + expect( + ds.modifyQuery( + { query: 'test:"value"', refId: 'A' }, + { type: 'ADD_FILTER_OUT', options: { key: 'test', value: 'value' } } + ).query + ).toBe('test:"value" AND -test:"value"'); + }); + }); }); describe('addAdhocFilters', () => { diff --git a/public/app/plugins/datasource/elasticsearch/datasource.ts b/public/app/plugins/datasource/elasticsearch/datasource.ts index 61b38b49f4d..7a6e98f4f62 100644 --- a/public/app/plugins/datasource/elasticsearch/datasource.ts +++ b/public/app/plugins/datasource/elasticsearch/datasource.ts @@ -897,27 +897,38 @@ export class ElasticDatasource } let expression = query.query ?? ''; - switch (action.type) { - case 'ADD_FILTER': { - // This gives the user the ability to toggle a filter on and off. - expression = queryHasFilter(expression, action.options.key, action.options.value) - ? removeFilterFromQuery(expression, action.options.key, action.options.value) - : addFilterToQuery(expression, action.options.key, action.options.value); - break; + if (config.featureToggles.elasticToggleableFilters) { + switch (action.type) { + case 'ADD_FILTER': { + // This gives the user the ability to toggle a filter on and off. + expression = queryHasFilter(expression, action.options.key, action.options.value) + ? removeFilterFromQuery(expression, action.options.key, action.options.value) + : addFilterToQuery(expression, action.options.key, action.options.value); + break; + } + case 'ADD_FILTER_OUT': { + // If the opposite filter is present, remove it before adding the new one. + if (queryHasFilter(expression, action.options.key, action.options.value)) { + expression = removeFilterFromQuery(expression, action.options.key, action.options.value); + } + expression = addFilterToQuery(expression, action.options.key, action.options.value, '-'); + break; + } } - case 'ADD_FILTER_OUT': { - /** - * If there is a filter with the same key and value, remove it. - * This prevents the user from seeing no changes in the query when they apply - * this filter. - */ - if (queryHasFilter(expression, action.options.key, action.options.value)) { - expression = removeFilterFromQuery(expression, action.options.key, action.options.value); + } else { + // Legacy behavior + switch (action.type) { + case 'ADD_FILTER': { + expression = addFilterToQuery(expression, action.options.key, action.options.value); + break; + } + case 'ADD_FILTER_OUT': { + expression = addFilterToQuery(expression, action.options.key, action.options.value, '-'); + break; } - expression = addFilterToQuery(expression, action.options.key, action.options.value, '-'); - break; } } + return { ...query, query: expression }; }