Prometheus: Use new language provider methods for code completions and query hints (#106383)

* refactor language provider

* update tests

* more tests

* betterer and api endpoints

* copilot updates

* betterer

* remove default value

* prettier

* introduce new methods

* provide unit tests for labelValues

* update metadata fetch

* move all cache related stuff in caching.ts

* provide interface

* provide deprecation messages

* unit tests for new interface

* separation of concerns

* update tests

* fix unit test

* fix some types

* Revert "fix some types"

This reverts commit 7e64b93b5f.

* revert interface usage

* betterer

* use PrometheusLanguageProviderInterface in everywhere

* introduce resource clients

* unit tests

* act accordingly with the feature toggle

* some more unit tests

* add feature toggle

* Revert "add feature toggle"

This reverts commit 5c93ac324f.

* remove feature toggle

* update tests

* backward compatibility

* fix scope issues

* comment update

* stronger types

* prettier

* betterer

* use new methods in metrics browser and query field

* always return data

* Revert "always return data"

This reverts commit 38e493c189.

* Revert "Revert "always return data""

This reverts commit b5d3b5d2b0.

* handle error

* lint

* use new method in query builder

* fix metrics modal tests too

* use labelValues method while searching in combobox

* update metrics modal regex search

* lint

* fix unit test

* introduce resource clients and better refactoring

* prettier

* type fixes

* betterer

* no empty matcher for series calls

* better matchers

* add additional tests

* proper match string for series

* introduce series cache

* introduce series cache for series label values

* lint

* cache values too

* utf8 safe label values query with series endpoint

* fix unit tests

* caching for labels api client

* betterer

* support new language provider methods in variable editor

* use queries and adhoc filters to extract matchers

* filter out __name__

* improve match string in series query label value calls

* update unit tests

* betterer

* use new language provider methods in completions and query hints

* betterer
This commit is contained in:
ismail simsek
2025-06-18 20:57:16 +02:00
committed by GitHub
parent f273c1c373
commit 17ad7af3b8
6 changed files with 28 additions and 16 deletions
@@ -16,6 +16,10 @@ const dataProviderSettings = {
},
getLabelKeys: jest.fn(),
getLabelValues: jest.fn(),
queryLabelKeys: jest.fn(),
queryLabelValues: jest.fn(),
retrieveLabelKeys: jest.fn(),
retrieveMetricsMetadata: jest.fn(),
getSeriesLabels: jest.fn(),
getSeriesValues: jest.fn(),
metrics: [],
@@ -168,7 +168,13 @@ async function getLabelNames(
return Promise.resolve(dataProvider.getAllLabelNames());
} else {
const selector = makeSelector(metric, otherLabels);
return await dataProvider.getSeriesLabels(timeRange, selector, otherLabels);
const labelNames = await dataProvider.getSeriesLabels(timeRange, selector);
// Exclude __name__ from output
otherLabels.push({ name: '__name__', value: '', op: '!=' });
const usedLabelNames = new Set(otherLabels.map((l) => l.name));
// names used in the query
return labelNames.filter((l) => !usedLabelNames.has(l));
}
}
@@ -38,10 +38,10 @@ export interface DataProviderParams {
export class DataProvider {
readonly languageProvider: PrometheusLanguageProviderInterface;
readonly historyProvider: Array<HistoryItem<PromQuery>>;
readonly getSeriesLabels: typeof this.languageProvider.getSeriesLabels;
readonly getSeriesValues: typeof this.languageProvider.getSeriesValues;
readonly getAllLabelNames: typeof this.languageProvider.getLabelKeys;
readonly getLabelValues: typeof this.languageProvider.getLabelValues;
readonly getSeriesLabels: typeof this.languageProvider.queryLabelKeys;
readonly getSeriesValues: typeof this.languageProvider.queryLabelValues;
readonly getAllLabelNames: typeof this.languageProvider.retrieveLabelKeys;
readonly getLabelValues: typeof this.languageProvider.queryLabelValues;
readonly metricNamesSuggestionLimit: number;
/**
* The text that's been typed so far within the current {@link Monaco.Range | Range}.
@@ -58,10 +58,10 @@ export class DataProvider {
this.inputInRange = '';
this.metricNamesSuggestionLimit = this.languageProvider.datasource.metricNamesAutocompleteSuggestionLimit;
this.suggestionsIncomplete = false;
this.getSeriesLabels = this.languageProvider.getSeriesLabels.bind(this.languageProvider);
this.getSeriesValues = this.languageProvider.getSeriesValues.bind(this.languageProvider);
this.getAllLabelNames = this.languageProvider.getLabelKeys.bind(this.languageProvider);
this.getLabelValues = this.languageProvider.getLabelValues.bind(this.languageProvider);
this.getSeriesLabels = this.languageProvider.queryLabelKeys.bind(this.languageProvider);
this.getSeriesValues = this.languageProvider.queryLabelValues.bind(this.languageProvider);
this.getAllLabelNames = this.languageProvider.retrieveLabelKeys.bind(this.languageProvider);
this.getLabelValues = this.languageProvider.queryLabelValues.bind(this.languageProvider);
}
getHistory(): string[] {
@@ -69,11 +69,11 @@ export class DataProvider {
}
getAllMetricNames(): string[] {
return this.languageProvider.metrics;
return this.languageProvider.retrieveMetrics();
}
metricNamesToMetrics(metricNames: string[]): Metric[] {
const { metricsMetadata } = this.languageProvider;
const metricsMetadata = this.languageProvider.retrieveMetricsMetadata();
const result: Metric[] = metricNames.map((m) => {
const metaItem = metricsMetadata?.[m];
return {
@@ -24,6 +24,8 @@ export class EmptyLanguageProviderMock {
queryLabelKeys = jest.fn().mockResolvedValue([]);
queryLabelValues = jest.fn().mockResolvedValue([]);
retrieveLabelKeys = jest.fn().mockReturnValue([]);
retrieveMetricsMetadata = jest.fn().mockReturnValue({});
retrieveMetricsMetadata = jest
.fn()
.mockReturnValue({ histogram_metric_sum: { type: 'counter', help: '', unit: 'sum' } });
queryMetricsMetadata = jest.fn().mockResolvedValue({});
}
@@ -55,7 +55,7 @@ describe('getQueryHints()', () => {
],
},
];
const mock: unknown = { languageProvider: { metricsMetadata: { foo: { type: 'counter' } } } };
const mock: unknown = { languageProvider: { retrieveMetricsMetadata: () => ({ foo: { type: 'counter' } }) } };
const datasource = mock as PrometheusDatasource;
let hints = getQueryHints('foo', series, datasource);
@@ -213,7 +213,7 @@ describe('getQueryHints()', () => {
],
},
];
const mock: unknown = { languageProvider: { metricsMetadata: { foo: { type: 'histogram' } } } };
const mock: unknown = { languageProvider: { retrieveMetricsMetadata: () => ({ foo: { type: 'histogram' } }) } };
const datasource = mock as PrometheusDatasource;
let hints = getQueryHints('foo', series, datasource);
@@ -234,7 +234,7 @@ describe('getQueryHints()', () => {
],
},
];
const mock: unknown = { languageProvider: { metricsMetadata: { foo: { type: 'histogram' } } } };
const mock: unknown = { languageProvider: { retrieveMetricsMetadata: () => ({ foo: { type: 'histogram' } }) } };
const datasource = mock as PrometheusDatasource;
let hints = getQueryHints(queryWithNativeHistogramFunction, series, datasource);
@@ -17,7 +17,7 @@ export const SUM_HINT_THRESHOLD_COUNT = 20;
export function getQueryHints(query: string, series?: unknown[], datasource?: PrometheusDatasource): QueryHint[] {
const hints = [];
const metricsMetadata = datasource?.languageProvider?.metricsMetadata;
const metricsMetadata = datasource?.languageProvider?.retrieveMetricsMetadata();
// ..._bucket metric needs a histogram_quantile()
// this regex also prevents hints from being shown when a query already has a function