Chore: Remove prometheusCodeModeMetricNamesSearch feature toggle (#109024)

* remove feature toggle prometheusCodeModeMetricNamesSearch

* remove code that relies on prometheusCodeModeMetricNamesSearch feature toggle

* remove code that related to prometheusCodeModeMetricNamesSearch feature toggle

* remove commented code lines

* remove commented code line

* Put codeModeMetricNamesSuggestionLimit selector back

* remove redundant unit test
This commit is contained in:
ismail simsek 2025-08-27 15:11:58 +02:00 committed by GitHub
parent b6226c6173
commit 5fe58431d4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 5 additions and 462 deletions

View File

@ -4367,8 +4367,6 @@ exports[`no gf-form usage`] = {
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"],
[0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"]
],
"packages/grafana-prometheus/src/querybuilder/components/PromQueryCodeEditor.tsx:5381": [

View File

@ -321,10 +321,6 @@ export interface FeatureToggles {
*/
cachingOptimizeSerializationMemoryUsage?: boolean;
/**
* Enables search for metric names in Code Mode, to improve performance when working with an enormous number of metric names
*/
prometheusCodeModeMetricNamesSearch?: boolean;
/**
* Add cumulative and window functions to the add field from calculation transformation
* @default true
*/

View File

@ -11,9 +11,6 @@ import type { Situation } from './situation';
const history: string[] = ['previous_metric_name_1', 'previous_metric_name_2', 'previous_metric_name_3'];
const dataProviderSettings = {
languageProvider: {
datasource: {
metricNamesAutocompleteSuggestionLimit: DEFAULT_COMPLETION_LIMIT,
},
queryLabelKeys: jest.fn(),
queryLabelValues: jest.fn(),
retrieveLabelKeys: jest.fn(),
@ -31,9 +28,6 @@ const metrics = {
beforeEach(() => {
dataProvider = new DataProvider(dataProviderSettings);
jest.replaceProperty(config, 'featureToggles', {
prometheusCodeModeMetricNamesSearch: true,
});
});
afterEach(() => {
@ -220,30 +214,6 @@ describe.each(metricNameCompletionSituations)('metric name completions in situat
expect(completions.length).toBeLessThanOrEqual(expectedCompletionsCount);
});
it('should enable autocomplete suggestions update when the number of metric names is greater than the limit', async () => {
const situation: Situation = {
type: situationType,
};
// Do not cross the metrics names threshold
jest.spyOn(dataProvider, 'getAllMetricNames').mockReturnValueOnce(metrics.atLimit);
dataProvider.monacoSettings.setInputInRange('name_1');
await getCompletions(situation, dataProvider, timeRange);
expect(dataProvider.monacoSettings.suggestionsIncomplete).toBe(false);
// Cross the metric names threshold, without text input
jest.spyOn(dataProvider, 'queryMetricNames').mockResolvedValue(metrics.beyondLimit);
dataProvider.monacoSettings.setInputInRange('');
await getCompletions(situation, dataProvider, timeRange);
expect(dataProvider.monacoSettings.suggestionsIncomplete).toBe(true);
// Cross the metric names threshold, with text input
jest.spyOn(dataProvider, 'getAllMetricNames').mockReturnValueOnce(metrics.beyondLimit);
dataProvider.monacoSettings.setInputInRange('name_1');
await getCompletions(situation, dataProvider, timeRange);
expect(dataProvider.monacoSettings.suggestionsIncomplete).toBe(true);
});
it('should handle complex queries efficiently', async () => {
const situation: Situation = {
type: situationType,

View File

@ -72,24 +72,6 @@ async function getAllMetricNamesCompletions(
): Promise<Completion[]> {
let metricNames = await dataProvider.queryMetricNames(timeRange, searchTerm);
if (
config.featureToggles.prometheusCodeModeMetricNamesSearch &&
metricNames.length > dataProvider.metricNamesSuggestionLimit
) {
const { monacoSettings } = dataProvider;
monacoSettings.enableAutocompleteSuggestionsUpdate();
if (monacoSettings.inputInRange) {
metricNames = filterMetricNames({
metricNames,
inputText: monacoSettings.inputInRange,
limit: dataProvider.metricNamesSuggestionLimit,
});
} else {
metricNames = metricNames.slice(0, dataProvider.metricNamesSuggestionLimit);
}
}
return dataProvider.metricNamesToMetrics(metricNames).map((metric) => ({
type: 'METRIC_NAME',
label: metric.name,

View File

@ -40,7 +40,6 @@ export class DataProvider {
readonly languageProvider: PrometheusLanguageProviderInterface;
readonly historyProvider: Array<HistoryItem<PromQuery>>;
readonly metricNamesSuggestionLimit: number = DEFAULT_COMPLETION_LIMIT;
readonly queryLabelKeys: typeof this.languageProvider.queryLabelKeys;
readonly queryLabelValues: typeof this.languageProvider.queryLabelValues;
/**
@ -50,13 +49,11 @@ export class DataProvider {
* This is useful with fuzzy searching items to provide as Monaco autocomplete suggestions.
*/
private inputInRange: string;
private suggestionsIncomplete: boolean;
constructor(params: DataProviderParams) {
this.languageProvider = params.languageProvider;
this.historyProvider = params.historyProvider;
this.inputInRange = '';
this.suggestionsIncomplete = false;
this.queryLabelKeys = this.languageProvider.queryLabelKeys.bind(this.languageProvider);
this.queryLabelValues = this.languageProvider.queryLabelValues.bind(this.languageProvider);
@ -111,33 +108,14 @@ export class DataProvider {
return result;
}
private enableAutocompleteSuggestionsUpdate(): void {
this.suggestionsIncomplete = true;
dispatchEvent(
new CustomEvent(CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT, {
detail: { limit: this.metricNamesSuggestionLimit, datasourceUid: this.languageProvider.datasource.uid },
})
);
}
private setInputInRange(textInput: string): void {
this.inputInRange = textInput;
}
get monacoSettings() {
return {
/**
* Enable autocomplete suggestions update on every input change.
*
* @remarks
* If fuzzy search is used in `getCompletions` to trim down results to improve performance,
* we need to instruct Monaco to update the completions on every input change, so that the
* completions reflect the current input.
*/
enableAutocompleteSuggestionsUpdate: this.enableAutocompleteSuggestionsUpdate.bind(this),
inputInRange: this.inputInRange,
setInputInRange: this.setInputInRange.bind(this),
suggestionsIncomplete: this.suggestionsIncomplete,
};
}
}

View File

@ -349,19 +349,5 @@ describe('monaco-completion-provider', () => {
expect(dataProvider.monacoSettings.setInputInRange).toHaveBeenCalled();
});
it('should return incomplete status from data provider', async () => {
dataProvider.monacoSettings.suggestionsIncomplete = true;
mockGetCompletions.mockResolvedValue([]);
const model = createMockModel('test');
const position = createMockPosition(4);
const { provider } = getCompletionProvider(monaco, dataProvider, timeRange);
const result = await (provider.provideCompletionItems as Function)(model, position);
expect(result?.incomplete).toBe(true);
});
});
});

View File

@ -146,7 +146,7 @@ export function getCompletionProvider(
: undefined,
}));
return { suggestions, incomplete: dataProvider.monacoSettings.suggestionsIncomplete };
return { suggestions };
});
};

View File

@ -1,22 +1,13 @@
// Core Grafana history https://github.com/grafana/grafana/blob/v11.0.0-preview/public/app/plugins/datasource/prometheus/configuration/PromSettings.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { render, screen } from '@testing-library/react';
import { SyntheticEvent } from 'react';
import { SelectableValue } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config } from '@grafana/runtime';
import { countError } from '../constants';
import { createDefaultConfigOptions } from '../test/mocks/datasource';
import { getValueFromEventItem, PromSettings } from './PromSettings';
beforeEach(() => {
jest.replaceProperty(config, 'featureToggles', {
prometheusCodeModeMetricNamesSearch: true,
});
});
describe('PromSettings', () => {
describe('getValueFromEventItem', () => {
describe('when called with undefined', () => {
@ -72,47 +63,6 @@ describe('PromSettings', () => {
render(<PromSettings onOptionsChange={() => {}} options={options} />);
expect(screen.getByText('GET')).toBeInTheDocument();
});
it('should show a valid metric name count if codeModeMetricNamesSuggestionLimit is configured correctly', () => {
const options = defaultProps;
const { getByTestId, queryByText } = render(<PromSettings onOptionsChange={() => {}} options={options} />);
const input = getByTestId(
selectors.components.DataSource.Prometheus.configPage.codeModeMetricNamesSuggestionLimit
);
// Non-negative integer
fireEvent.change(input, { target: { value: '3000' } });
fireEvent.blur(input);
expect(queryByText(countError)).not.toBeInTheDocument();
// Non-negative integer with scientific notation
fireEvent.change(input, { target: { value: '1e5' } });
fireEvent.blur(input);
expect(queryByText(countError)).not.toBeInTheDocument();
// Non-negative integer with decimal scientific notation
fireEvent.change(input, { target: { value: '1.4e4' } });
fireEvent.blur(input);
expect(queryByText(countError)).not.toBeInTheDocument();
});
it('should show the expected error when an invalid value is provided for codeModeMetricNamesSuggestionLimit', () => {
const options = defaultProps;
const { getByTestId, queryByText } = render(<PromSettings onOptionsChange={() => {}} options={options} />);
const input = getByTestId(
selectors.components.DataSource.Prometheus.configPage.codeModeMetricNamesSuggestionLimit
);
// No negative values
fireEvent.change(input, { target: { value: '-50' } });
fireEvent.blur(input);
expect(queryByText(countError)).toBeInTheDocument();
// No negative values with scientific notation
fireEvent.change(input, { target: { value: '-5e5' } });
fireEvent.blur(input);
expect(queryByText(countError)).toBeInTheDocument();
});
it('should have a series endpoint configuration element', () => {
const options = defaultProps;

View File

@ -11,11 +11,9 @@ import {
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { ConfigSubSection } from '@grafana/plugin-ui';
import { config } from '@grafana/runtime';
import { InlineField, Input, Select, Switch, TextLink, useTheme2 } from '@grafana/ui';
import {
countError,
DEFAULT_SERIES_LIMIT,
DURATION_REGEX,
durationError,
@ -23,7 +21,6 @@ import {
NON_NEGATIVE_INTEGER_REGEX,
PROM_CONFIG_LABEL_WIDTH,
seriesLimitError,
SUGGESTIONS_LIMIT,
} from '../constants';
import { QueryEditorMode } from '../querybuilder/shared/types';
import { defaultPrometheusQueryOverlapWindow } from '../querycache/QueryCache';
@ -55,10 +52,6 @@ type ValidDuration = {
incrementalQueryOverlapWindow: string;
};
type ValidCount = {
codeModeMetricNamesSuggestionLimit: string;
};
const prometheusFlavorSelectItems: PrometheusSelectItemsType = [
{ value: PromApplication.Prometheus, label: PromApplication.Prometheus },
{ value: PromApplication.Cortex, label: PromApplication.Cortex },
@ -99,10 +92,6 @@ export const PromSettings = (props: Props) => {
incrementalQueryOverlapWindow: '',
});
const [validCount, updateValidCount] = useState<ValidCount>({
codeModeMetricNamesSuggestionLimit: '',
});
const [seriesLimit, setSeriesLimit] = useState<string>(
optionsWithDefaults.jsonData.seriesLimit?.toString() || `${DEFAULT_SERIES_LIMIT}`
);
@ -400,58 +389,6 @@ export const PromSettings = (props: Props) => {
</div>
</div>
{config.featureToggles.prometheusCodeModeMetricNamesSearch && (
<div className="gf-form-inline">
<div className="gf-form">
<InlineField
label={t(
'grafana-prometheus.configuration.prom-settings.label-metric-names-suggestion-limit',
'Metric names suggestion limit'
)}
labelWidth={PROM_CONFIG_LABEL_WIDTH}
tooltip={
<>
<Trans i18nKey="grafana-prometheus.configuration.prom-settings.tooltip-metric-names-suggestion-limit">
The maximum number of metric names that may appear as autocomplete suggestions in the query
editor&apos;s Code mode.
</Trans>
</>
}
interactive={true}
disabled={optionsWithDefaults.readOnly}
>
<>
<Input
className="width-20"
value={optionsWithDefaults.jsonData.codeModeMetricNamesSuggestionLimit}
onChange={onChangeHandler(
'codeModeMetricNamesSuggestionLimit',
optionsWithDefaults,
onOptionsChange
)}
spellCheck={false}
placeholder={SUGGESTIONS_LIMIT.toString()}
onBlur={(e) =>
updateValidCount({
...validCount,
codeModeMetricNamesSuggestionLimit: e.currentTarget.value,
})
}
data-testid={
selectors.components.DataSource.Prometheus.configPage.codeModeMetricNamesSuggestionLimit
}
/>
{validateInput(
validCount.codeModeMetricNamesSuggestionLimit,
NON_NEGATIVE_INTEGER_REGEX,
countError
)}
</>
</InlineField>
</div>
</div>
)}
<div className="gf-form-inline">
<div className="gf-form max-width-30">
<InlineField

View File

@ -33,8 +33,6 @@ export const METRIC_LABEL = '__name__';
export const durationError = 'Value is not valid, you can use number with time unit specifier: y, M, w, d, h, m, s';
export const countError = 'Value is not valid, you can use non-negative integers, including scientific notation';
export const seriesLimitError =
'Value is not valid, you can use only numbers or leave it empty to use default limit or set 0 to have no limit.';

View File

@ -41,12 +41,7 @@ import {
import { addLabelToQuery } from './add_label_to_query';
import { PrometheusAnnotationSupport } from './annotations';
import {
DEFAULT_SERIES_LIMIT,
GET_AND_POST_METADATA_ENDPOINTS,
InstantQueryRefIdIndex,
SUGGESTIONS_LIMIT,
} from './constants';
import { DEFAULT_SERIES_LIMIT, GET_AND_POST_METADATA_ENDPOINTS, InstantQueryRefIdIndex } from './constants';
import { interpolateQueryExpr, prometheusRegularEscape } from './escaping';
import {
exportToAbstractQuery,
@ -96,7 +91,6 @@ export class PrometheusDatasource
interval: string;
languageProvider: PrometheusLanguageProviderInterface;
lookupsDisabled: boolean;
metricNamesAutocompleteSuggestionLimit: number;
ruleMappings: RuleQueryMapping;
seriesEndpoint: boolean;
seriesLimit: number;
@ -132,8 +126,6 @@ export class PrometheusDatasource
this.id = instanceSettings.id;
this.interval = instanceSettings.jsonData.timeInterval || '15s';
this.lookupsDisabled = instanceSettings.jsonData.disableMetricsLookup ?? false;
this.metricNamesAutocompleteSuggestionLimit =
instanceSettings.jsonData.codeModeMetricNamesSuggestionLimit ?? SUGGESTIONS_LIMIT;
this.ruleMappings = {};
this.seriesEndpoint = instanceSettings.jsonData.seriesEndpoint ?? false;
this.seriesLimit = instanceSettings.jsonData.seriesLimit ?? DEFAULT_SERIES_LIMIT;

View File

@ -168,7 +168,6 @@
"label-disable-recording-rules-beta": "Disable recording rules (beta)",
"label-http-method": "HTTP method",
"label-incremental-querying-beta": "Incremental querying (beta)",
"label-metric-names-suggestion-limit": "Metric names suggestion limit",
"label-prom-type-version": "{{promType}} version",
"label-prometheus-type": "Prometheus type",
"label-query-overlap-window": "Query overlap window",
@ -189,7 +188,6 @@
"tooltip-disable-recording-rules-beta": "This feature will disable recording rules. Turn this on to improve dashboard performance",
"tooltip-http-method": "You can use either POST or GET HTTP method to query your Prometheus data source. POST is the recommended method as it allows bigger queries. Change this to GET if you have a Prometheus version older than 2.1 or if POST requests are restricted in your network.",
"tooltip-incremental-querying-beta": "This feature will change the default behavior of relative queries to always request fresh data from the prometheus instance, instead query results will be cached, and only new records are requested. Turn this on to decrease database and network load.",
"tooltip-metric-names-suggestion-limit": "The maximum number of metric names that may appear as autocomplete suggestions in the query editor's Code mode.",
"tooltip-prom-type-version": "Use this to set the version of your {{promType}} instance if it is not automatically configured.",
"tooltip-prometheus-type": "Set this to the type of your prometheus database, e.g. Prometheus, Cortex, Mimir or Thanos. Changing this field will save your current settings. Certain types of Prometheus supports or does not support various APIs. For example, some types support regex matching for label queries to improve performance. Some types have an API for metadata. If you set this incorrectly you may experience odd behavior when querying metrics and labels. Please check your Prometheus documentation to ensure you enter the correct type.",
"tooltip-query-overlap-window": "Set a duration like {{example1}} or {{example2}} or {{example3}}. Default of {{default}}. This duration will be added to the duration of each incremental request.",
@ -431,10 +429,6 @@
"title-options": "Options",
"tooltip-min-step": "An additional lower limit for the step parameter of the Prometheus query and for the <2>{{interval}}</2> and <4>{{rateInterval}}</4> variables."
},
"prom-query-code-editor-autocomplete-info": {
"autocomplete-suggestions-limited": "Autocomplete suggestions limited",
"tooltip-autocomplete-suggestions-limited": "The number of metric names exceeds the autocomplete limit. Only the {{autocompleteLimit}}-most relevant metrics are displayed. You can adjust the threshold in the data source settings."
},
"prom-query-editor-selector": {
"body-syntax-error": "There is a syntax error, or the query structure cannot be visualized when switching to the builder mode. Parts of the query may be lost.",
"confirmText-continue": "Continue",

View File

@ -1,148 +0,0 @@
import { render, screen, fireEvent, createEvent } from '@testing-library/react';
import { cloneDeep, defaultsDeep } from 'lodash';
import { PluginMeta, PluginType } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { config } from '@grafana/runtime';
import { CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT } from '../../components/monaco-query-field/monaco-completion-provider/data_provider';
import { PromQueryEditorProps } from '../../components/types';
import { PrometheusDatasource } from '../../datasource';
import { PrometheusLanguageProviderInterface } from '../../language_provider';
import { EmptyLanguageProviderMock } from '../../language_provider.mock';
import { PromQuery } from '../../types';
import { QueryEditorMode } from '../shared/types';
import { PromQueryEditorSelector } from './PromQueryEditorSelector';
beforeEach(() => {
jest.replaceProperty(config, 'featureToggles', {
prometheusCodeModeMetricNamesSearch: true,
});
});
// We need to mock this because it seems jest has problem importing monaco in tests
jest.mock('../../components/monaco-query-field/MonacoQueryFieldWrapper', () => {
return {
MonacoQueryFieldWrapper: () => {
return 'MonacoQueryFieldWrapper';
},
};
});
jest.mock('@grafana/runtime', () => {
return {
...jest.requireActual('@grafana/runtime'),
reportInteraction: jest.fn(),
};
});
const defaultQuery = {
refId: 'A',
expr: 'metric{label1="foo", label2="bar"}',
};
const defaultMeta: PluginMeta = {
id: '',
name: '',
type: PluginType.datasource,
info: {
author: {
name: 'tester',
},
description: 'testing',
links: [],
logos: {
large: '',
small: '',
},
screenshots: [],
updated: '',
version: '',
},
module: '',
baseUrl: '',
};
const getDefaultDatasource = (jsonDataOverrides = {}) =>
new PrometheusDatasource(
{
id: 1,
uid: 'myDataSourceUid',
type: 'prometheus',
name: 'prom-test',
access: 'proxy',
url: '',
jsonData: jsonDataOverrides,
meta: defaultMeta,
readOnly: false,
},
undefined,
new EmptyLanguageProviderMock() as unknown as PrometheusLanguageProviderInterface
);
const defaultProps = {
datasource: getDefaultDatasource(),
query: defaultQuery,
onRunQuery: () => {},
onChange: () => {},
};
const autocompleteInfoSelector = selectors.components.DataSource.Prometheus.queryEditor.code.metricsCountInfo;
describe('PromQueryEditorSelector', () => {
it('does not show autocomplete info when the code editor first displays', async () => {
const { queryByTestId } = renderWithCodeMode();
expect(await screen.findByText('MonacoQueryFieldWrapper')).toBeInTheDocument();
expect(queryByTestId(autocompleteInfoSelector)).not.toBeInTheDocument();
});
it('shows autocomplete info when the expected event fires', async () => {
const { findByTestId } = renderWithCodeMode();
fireEvent(
window,
createEvent(
CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT,
window,
{
detail: { limit: 100, datasourceUid: 'myDataSourceUid' },
},
{ EventType: 'CustomEvent' }
)
);
expect(await screen.findByText('MonacoQueryFieldWrapper')).toBeInTheDocument();
const autocompleteInfo = await findByTestId(autocompleteInfoSelector);
expect(autocompleteInfo).toBeInTheDocument();
});
it('does not show autocomplete info when the triggering event refers to a different data source', async () => {
const { queryByTestId } = renderWithCodeMode();
fireEvent(
window,
createEvent(
CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT,
window,
{
detail: { limit: 100, datasourceUid: 'theWrongUid' },
},
{ EventType: 'CustomEvent' }
)
);
expect(await screen.findByText('MonacoQueryFieldWrapper')).toBeInTheDocument();
const autocompleteInfo = await queryByTestId(autocompleteInfoSelector);
expect(autocompleteInfo).not.toBeInTheDocument();
});
});
function renderWithCodeMode() {
return renderWithProps({ editorMode: QueryEditorMode.Code, expr: 'my_metric' });
}
function renderWithProps(overrides?: Partial<PromQuery>, componentProps: Partial<PromQueryEditorProps> = {}) {
const query = defaultsDeep(overrides ?? {}, cloneDeep(defaultQuery));
const onChange = jest.fn();
const allProps = { ...defaultProps, ...componentProps };
const stuff = render(<PromQueryEditorSelector {...allProps} query={query} onChange={onChange} />);
return { onChange, ...stuff };
}

View File

@ -1,76 +0,0 @@
import { useState, useEffect, useCallback } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { Trans, t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { IconButton, Text, Stack } from '@grafana/ui';
import {
CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT,
isSuggestionsIncompleteEvent,
} from '../../components/monaco-query-field/monaco-completion-provider/data_provider';
import { PromQueryEditorProps } from '../../components/types';
import { QueryEditorMode } from '../shared/types';
interface Props {
datasourceUid: PromQueryEditorProps['datasource']['uid'];
editorMode: QueryEditorMode;
}
export function PromQueryCodeEditorAutocompleteInfo(props: Readonly<Props>) {
const [autocompleteLimit, setAutocompleteLimit] = useState('n');
const [autocompleteLimitExceeded, setAutocompleteLimitExceeded] = useState(false);
const handleSuggestionsIncompleteEvent = useCallback(
(e: Event) => {
if (!isSuggestionsIncompleteEvent(e)) {
return;
}
if (e.detail.datasourceUid === props.datasourceUid) {
setAutocompleteLimitExceeded(true);
setAutocompleteLimit(e.detail.limit.toString());
}
},
[props.datasourceUid]
);
useEffect(() => {
window.addEventListener(CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT, handleSuggestionsIncompleteEvent);
return () => {
window.removeEventListener(CODE_MODE_SUGGESTIONS_INCOMPLETE_EVENT, handleSuggestionsIncompleteEvent);
};
}, [handleSuggestionsIncompleteEvent]);
const showCodeModeAutocompleteDisclaimer = (): boolean => {
return (
Boolean(config.featureToggles.prometheusCodeModeMetricNamesSearch) &&
props.editorMode === QueryEditorMode.Code &&
autocompleteLimitExceeded
);
};
if (!showCodeModeAutocompleteDisclaimer()) {
return null;
}
return (
<div data-testid={selectors.components.DataSource.Prometheus.queryEditor.code.metricsCountInfo}>
<Stack direction="row" gap={1}>
<Text color="secondary" element="p" italic={true}>
<Trans i18nKey="grafana-prometheus.querybuilder.prom-query-code-editor-autocomplete-info.autocomplete-suggestions-limited">
Autocomplete suggestions limited
</Trans>
</Text>
<IconButton
name="info-circle"
tooltip={t(
'grafana-prometheus.querybuilder.prom-query-code-editor-autocomplete-info.tooltip-autocomplete-suggestions-limited',
'The number of metric names exceeds the autocomplete limit. Only the {{autocompleteLimit}}-most relevant metrics are displayed. You can adjust the threshold in the data source settings.',
{ autocompleteLimit }
)}
/>
</Stack>
</div>
);
}

View File

@ -22,7 +22,6 @@ import { changeEditorMode, getQueryWithDefaults } from '../state';
import { PromQueryBuilderContainer } from './PromQueryBuilderContainer';
import { PromQueryBuilderOptions } from './PromQueryBuilderOptions';
import { PromQueryCodeEditor } from './PromQueryCodeEditor';
import { PromQueryCodeEditorAutocompleteInfo } from './PromQueryCodeEditorAutocompleteInfo';
type Props = PromQueryEditorProps;
@ -148,7 +147,6 @@ export const PromQueryEditorSelector = memo<Props>((props) => {
<Trans i18nKey="grafana-prometheus.querybuilder.prom-query-editor-selector.run-queries">Run queries</Trans>
</Button>
)}
<PromQueryCodeEditorAutocompleteInfo datasourceUid={props.datasource.uid} editorMode={editorMode} />
<div data-testid={selectors.components.DataSource.Prometheus.queryEditor.editorToggle}>
<QueryEditorModeToggle mode={editorMode} onChange={onEditorModeChange} />
</div>

View File

@ -49,7 +49,6 @@ export interface PromOptions extends DataSourceJsonData {
allowAsRecordingRulesTarget?: boolean;
sigV4Auth?: boolean;
oauthPassThru?: boolean;
codeModeMetricNamesSuggestionLimit?: number;
seriesEndpoint?: boolean;
seriesLimit?: number;
}

View File

@ -533,13 +533,6 @@ var (
Owner: grafanaOperatorExperienceSquad,
FrontendOnly: false,
},
{
Name: "prometheusCodeModeMetricNamesSearch",
Description: "Enables search for metric names in Code Mode, to improve performance when working with an enormous number of metric names",
FrontendOnly: true,
Stage: FeatureStageExperimental,
Owner: grafanaOSSBigTent,
},
{
Name: "addFieldFromCalculationStatFunctions",
Description: "Add cumulative and window functions to the add field from calculation transformation",

View File

@ -70,7 +70,6 @@ queryServiceFromUI,experimental,@grafana/grafana-datasources-core-services,false
queryServiceFromExplore,experimental,@grafana/grafana-datasources-core-services,false,false,true
cloudWatchBatchQueries,preview,@grafana/aws-datasources,false,false,false
cachingOptimizeSerializationMemoryUsage,experimental,@grafana/grafana-operator-experience-squad,false,false,false
prometheusCodeModeMetricNamesSearch,experimental,@grafana/oss-big-tent,false,false,true
addFieldFromCalculationStatFunctions,GA,@grafana/dataviz-squad,false,false,true
alertmanagerRemoteSecondary,experimental,@grafana/alerting-squad,false,false,false
alertingProvenanceLockWrites,experimental,@grafana/alerting-squad,false,false,false

1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
70 queryServiceFromExplore experimental @grafana/grafana-datasources-core-services false false true
71 cloudWatchBatchQueries preview @grafana/aws-datasources false false false
72 cachingOptimizeSerializationMemoryUsage experimental @grafana/grafana-operator-experience-squad false false false
prometheusCodeModeMetricNamesSearch experimental @grafana/oss-big-tent false false true
73 addFieldFromCalculationStatFunctions GA @grafana/dataviz-squad false false true
74 alertmanagerRemoteSecondary experimental @grafana/alerting-squad false false false
75 alertingProvenanceLockWrites experimental @grafana/alerting-squad false false false

View File

@ -291,10 +291,6 @@ const (
// If enabled, the caching backend gradually serializes query responses for the cache, comparing against the configured `[caching]max_value_mb` value as it goes. This can can help prevent Grafana from running out of memory while attempting to cache very large query responses.
FlagCachingOptimizeSerializationMemoryUsage = "cachingOptimizeSerializationMemoryUsage"
// FlagPrometheusCodeModeMetricNamesSearch
// Enables search for metric names in Code Mode, to improve performance when working with an enormous number of metric names
FlagPrometheusCodeModeMetricNamesSearch = "prometheusCodeModeMetricNamesSearch"
// FlagAddFieldFromCalculationStatFunctions
// Add cumulative and window functions to the add field from calculation transformation
FlagAddFieldFromCalculationStatFunctions = "addFieldFromCalculationStatFunctions"

View File

@ -2602,7 +2602,8 @@
"metadata": {
"name": "prometheusCodeModeMetricNamesSearch",
"resourceVersion": "1753448760331",
"creationTimestamp": "2024-04-04T20:38:23Z"
"creationTimestamp": "2024-04-04T20:38:23Z",
"deletionTimestamp": "2025-08-01T07:53:50Z"
},
"spec": {
"description": "Enables search for metric names in Code Mode, to improve performance when working with an enormous number of metric names",