diff --git a/public/app/plugins/datasource/prometheus/components/monaco-query-field/MonacoQueryField.tsx b/public/app/plugins/datasource/prometheus/components/monaco-query-field/MonacoQueryField.tsx index f62b079a35b..24989fa9ab7 100644 --- a/public/app/plugins/datasource/prometheus/components/monaco-query-field/MonacoQueryField.tsx +++ b/public/app/plugins/datasource/prometheus/components/monaco-query-field/MonacoQueryField.tsx @@ -138,7 +138,11 @@ const MonacoQueryField = (props: Props) => { return Promise.resolve(result); }; - const dataProvider = { getSeries, getHistory, getAllMetricNames }; + const getAllLabelNames = () => Promise.resolve(lpRef.current.getLabelKeys()); + + const getLabelValues = (labelName: string) => lpRef.current.getLabelValues(labelName); + + const dataProvider = { getSeries, getHistory, getAllMetricNames, getAllLabelNames, getLabelValues }; const completionProvider = getCompletionProvider(monaco, dataProvider); // completion-providers in monaco are not registered directly to editor-instances, diff --git a/public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/completions.ts b/public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/completions.ts index add020ebb4e..9d1b9394fbe 100644 --- a/public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/completions.ts +++ b/public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/completions.ts @@ -23,6 +23,8 @@ type Metric = { export type DataProvider = { getHistory: () => Promise; getAllMetricNames: () => Promise; + getAllLabelNames: () => Promise; + getLabelValues: (labelName: string) => Promise; getSeries: (selector: string) => Promise>; }; @@ -93,6 +95,23 @@ function makeSelector(metricName: string | undefined, labels: Label[]): string { return `{${allLabelTexts.join(',')}}`; } +async function getLabelNames( + metric: string | undefined, + otherLabels: Label[], + dataProvider: DataProvider +): Promise { + if (metric === undefined && otherLabels.length === 0) { + // if there is no filtering, we have to use a special endpoint + return dataProvider.getAllLabelNames(); + } else { + const selector = makeSelector(metric, otherLabels); + const data = await dataProvider.getSeries(selector); + const possibleLabelNames = Object.keys(data); // all names from prometheus + const usedLabelNames = new Set(otherLabels.map((l) => l.name)); // names used in the query + return possibleLabelNames.filter((l) => !usedLabelNames.has(l)); + } +} + async function getLabelNamesForCompletions( metric: string | undefined, suffix: string, @@ -100,11 +119,7 @@ async function getLabelNamesForCompletions( otherLabels: Label[], dataProvider: DataProvider ): Promise { - const selector = makeSelector(metric, otherLabels); - const data = await dataProvider.getSeries(selector); - const possibleLabelNames = Object.keys(data); // all names from prometheus - const usedLabelNames = new Set(otherLabels.map((l) => l.name)); // names used in the query - const labelNames = possibleLabelNames.filter((l) => !usedLabelNames.has(l)); + const labelNames = await getLabelNames(metric, otherLabels, dataProvider); return labelNames.map((text) => ({ type: 'LABEL_NAME', label: text, @@ -128,15 +143,29 @@ async function getLabelNamesForByCompletions( return getLabelNamesForCompletions(metric, '', false, otherLabels, dataProvider); } +async function getLabelValues( + metric: string | undefined, + labelName: string, + otherLabels: Label[], + dataProvider: DataProvider +): Promise { + if (metric === undefined && otherLabels.length === 0) { + // if there is no filtering, we have to use a special endpoint + return dataProvider.getLabelValues(labelName); + } else { + const selector = makeSelector(metric, otherLabels); + const data = await dataProvider.getSeries(selector); + return data[labelName] ?? []; + } +} + async function getLabelValuesForMetricCompletions( metric: string | undefined, labelName: string, otherLabels: Label[], dataProvider: DataProvider ): Promise { - const selector = makeSelector(metric, otherLabels); - const data = await dataProvider.getSeries(selector); - const values = data[labelName] ?? []; + const values = await getLabelValues(metric, labelName, otherLabels, dataProvider); return values.map((text) => ({ type: 'LABEL_VALUE', label: text,