mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
prometheus: monaco: improved suggestion-displaying (icons, help-text) (#38977)
* prometheus: monaco: better icons in popup * prometheus: monaco: add help-text to functions * prometheus: monaco: add help-text to metrics * better help-text
This commit is contained in:
parent
88ad9aad42
commit
e055ba3525
@ -56,7 +56,14 @@ const MonacoQueryField = (props: Props) => {
|
||||
|
||||
const getAllMetricNames = () => {
|
||||
const { metricsMetadata } = lpRef.current;
|
||||
const result = metricsMetadata == null ? [] : Object.keys(metricsMetadata);
|
||||
const result =
|
||||
metricsMetadata == null
|
||||
? []
|
||||
: Object.entries(metricsMetadata).map(([k, v]) => ({
|
||||
name: k,
|
||||
help: v[0].help,
|
||||
type: v[0].type,
|
||||
}));
|
||||
return Promise.resolve(result);
|
||||
};
|
||||
|
||||
|
@ -3,38 +3,56 @@ import { NeverCaseError } from './util';
|
||||
// FIXME: we should not load this from the "outside", but we cannot do that while we have the "old" query-field too
|
||||
import { FUNCTIONS } from '../../../promql';
|
||||
|
||||
export type CompletionType = 'HISTORY' | 'FUNCTION' | 'METRIC_NAME' | 'DURATION' | 'LABEL_NAME' | 'LABEL_VALUE';
|
||||
|
||||
type Completion = {
|
||||
type: CompletionType;
|
||||
label: string;
|
||||
insertText: string;
|
||||
detail?: string;
|
||||
documentation?: string;
|
||||
triggerOnInsert?: boolean;
|
||||
};
|
||||
|
||||
type Metric = {
|
||||
name: string;
|
||||
help: string;
|
||||
type: string;
|
||||
};
|
||||
|
||||
export type DataProvider = {
|
||||
getHistory: () => Promise<string[]>;
|
||||
getAllMetricNames: () => Promise<string[]>;
|
||||
getAllMetricNames: () => Promise<Metric[]>;
|
||||
getSeries: (selector: string) => Promise<Record<string, string[]>>;
|
||||
};
|
||||
|
||||
// we order items like: history, functions, metrics
|
||||
|
||||
async function getAllMetricNamesCompletions(dataProvider: DataProvider): Promise<Completion[]> {
|
||||
const names = await dataProvider.getAllMetricNames();
|
||||
return names.map((text) => ({
|
||||
label: text,
|
||||
insertText: text,
|
||||
const metrics = await dataProvider.getAllMetricNames();
|
||||
return metrics.map((metric) => ({
|
||||
type: 'METRIC_NAME',
|
||||
label: metric.name,
|
||||
insertText: metric.name,
|
||||
detail: `${metric.name} : ${metric.type}`,
|
||||
documentation: metric.help,
|
||||
}));
|
||||
}
|
||||
|
||||
function getAllFunctionsCompletions(): Completion[] {
|
||||
return FUNCTIONS.map((f) => ({
|
||||
type: 'FUNCTION',
|
||||
label: f.label,
|
||||
insertText: f.insertText ?? '', // i don't know what to do when this is nullish. it should not be.
|
||||
detail: f.detail,
|
||||
documentation: f.documentation,
|
||||
}));
|
||||
}
|
||||
|
||||
function getAllDurationsCompletions(): Completion[] {
|
||||
// FIXME: get a better list
|
||||
return ['5m', '1m', '30s', '15s'].map((text) => ({
|
||||
type: 'DURATION',
|
||||
label: text,
|
||||
insertText: text,
|
||||
}));
|
||||
@ -46,6 +64,7 @@ async function getAllHistoryCompletions(dataProvider: DataProvider): Promise<Com
|
||||
const allHistory = await dataProvider.getHistory();
|
||||
// FIXME: find a better history-limit
|
||||
return allHistory.slice(0, 10).map((expr) => ({
|
||||
type: 'HISTORY',
|
||||
label: expr,
|
||||
insertText: expr,
|
||||
}));
|
||||
@ -77,6 +96,7 @@ async function getLabelNamesForCompletions(
|
||||
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) => ({
|
||||
type: 'LABEL_NAME',
|
||||
label: text,
|
||||
insertText: `${text}${suffix}`,
|
||||
triggerOnInsert,
|
||||
@ -108,6 +128,7 @@ async function getLabelValuesForMetricCompletions(
|
||||
const data = await dataProvider.getSeries(selector);
|
||||
const values = data[labelName] ?? [];
|
||||
return values.map((text) => ({
|
||||
type: 'LABEL_VALUE',
|
||||
label: text,
|
||||
insertText: `"${text}"`, // FIXME: escaping strange characters?
|
||||
}));
|
||||
|
@ -1,8 +1,27 @@
|
||||
import type { Monaco, monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { getIntent } from './intent';
|
||||
import { getCompletions, DataProvider } from './completions';
|
||||
import { getCompletions, DataProvider, CompletionType } from './completions';
|
||||
import { NeverCaseError } from './util';
|
||||
|
||||
function getMonacoCompletionItemKind(type: CompletionType, monaco: Monaco): monacoTypes.languages.CompletionItemKind {
|
||||
switch (type) {
|
||||
case 'DURATION':
|
||||
return monaco.languages.CompletionItemKind.Unit;
|
||||
case 'FUNCTION':
|
||||
return monaco.languages.CompletionItemKind.Variable;
|
||||
case 'HISTORY':
|
||||
return monaco.languages.CompletionItemKind.Snippet;
|
||||
case 'LABEL_NAME':
|
||||
return monaco.languages.CompletionItemKind.Enum;
|
||||
case 'LABEL_VALUE':
|
||||
return monaco.languages.CompletionItemKind.EnumMember;
|
||||
case 'METRIC_NAME':
|
||||
return monaco.languages.CompletionItemKind.Constructor;
|
||||
default:
|
||||
throw new NeverCaseError(type);
|
||||
}
|
||||
}
|
||||
export function getCompletionProvider(
|
||||
monaco: Monaco,
|
||||
dataProvider: DataProvider
|
||||
@ -35,10 +54,12 @@ export function getCompletionProvider(
|
||||
// to stop it, we use a number-as-string sortkey,
|
||||
// so that monaco keeps the order we use
|
||||
const maxIndexDigits = items.length.toString().length;
|
||||
const suggestions = items.map((item, index) => ({
|
||||
kind: monaco.languages.CompletionItemKind.Text,
|
||||
const suggestions: monacoTypes.languages.CompletionItem[] = items.map((item, index) => ({
|
||||
kind: getMonacoCompletionItemKind(item.type, monaco),
|
||||
label: item.label,
|
||||
insertText: item.insertText,
|
||||
detail: item.detail,
|
||||
documentation: item.documentation,
|
||||
sortText: index.toString().padStart(maxIndexDigits, '0'), // to force the order we have
|
||||
range,
|
||||
command: item.triggerOnInsert
|
||||
|
Loading…
Reference in New Issue
Block a user