prometheus: monaco: allow listing label names + values without a metric (#41233)

* prometheus: monaco: allow listing label names + values without a metric

* removed comment
This commit is contained in:
Gábor Farkas 2021-11-03 11:20:04 +01:00 committed by GitHub
parent 72ae3235fa
commit 91da1bbb79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 9 deletions

View File

@ -138,7 +138,11 @@ const MonacoQueryField = (props: Props) => {
return Promise.resolve(result); 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); const completionProvider = getCompletionProvider(monaco, dataProvider);
// completion-providers in monaco are not registered directly to editor-instances, // completion-providers in monaco are not registered directly to editor-instances,

View File

@ -23,6 +23,8 @@ type Metric = {
export type DataProvider = { export type DataProvider = {
getHistory: () => Promise<string[]>; getHistory: () => Promise<string[]>;
getAllMetricNames: () => Promise<Metric[]>; getAllMetricNames: () => Promise<Metric[]>;
getAllLabelNames: () => Promise<string[]>;
getLabelValues: (labelName: string) => Promise<string[]>;
getSeries: (selector: string) => Promise<Record<string, string[]>>; getSeries: (selector: string) => Promise<Record<string, string[]>>;
}; };
@ -93,6 +95,23 @@ function makeSelector(metricName: string | undefined, labels: Label[]): string {
return `{${allLabelTexts.join(',')}}`; return `{${allLabelTexts.join(',')}}`;
} }
async function getLabelNames(
metric: string | undefined,
otherLabels: Label[],
dataProvider: DataProvider
): Promise<string[]> {
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( async function getLabelNamesForCompletions(
metric: string | undefined, metric: string | undefined,
suffix: string, suffix: string,
@ -100,11 +119,7 @@ async function getLabelNamesForCompletions(
otherLabels: Label[], otherLabels: Label[],
dataProvider: DataProvider dataProvider: DataProvider
): Promise<Completion[]> { ): Promise<Completion[]> {
const selector = makeSelector(metric, otherLabels); const labelNames = await getLabelNames(metric, otherLabels, dataProvider);
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));
return labelNames.map((text) => ({ return labelNames.map((text) => ({
type: 'LABEL_NAME', type: 'LABEL_NAME',
label: text, label: text,
@ -128,15 +143,29 @@ async function getLabelNamesForByCompletions(
return getLabelNamesForCompletions(metric, '', false, otherLabels, dataProvider); return getLabelNamesForCompletions(metric, '', false, otherLabels, dataProvider);
} }
async function getLabelValues(
metric: string | undefined,
labelName: string,
otherLabels: Label[],
dataProvider: DataProvider
): Promise<string[]> {
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( async function getLabelValuesForMetricCompletions(
metric: string | undefined, metric: string | undefined,
labelName: string, labelName: string,
otherLabels: Label[], otherLabels: Label[],
dataProvider: DataProvider dataProvider: DataProvider
): Promise<Completion[]> { ): Promise<Completion[]> {
const selector = makeSelector(metric, otherLabels); const values = await getLabelValues(metric, labelName, otherLabels, dataProvider);
const data = await dataProvider.getSeries(selector);
const values = data[labelName] ?? [];
return values.map((text) => ({ return values.map((text) => ({
type: 'LABEL_VALUE', type: 'LABEL_VALUE',
label: text, label: text,