Prometheus: UTF8 support in metrics browser (#98612)

* utf8 metrics for prometheus devenv

* introduce utf8 support

* completions and suggestions

* don't wrap the utf8 label in quotes

* linting

* support utf8 labels and metrics on visual query builder

* lint

* update raw view for utf8 metric syntax

* betterer

* support utf8 metric names in explore metrics

* utf8 support in grouop by

* utf8 support in label break down

* utf8 metric and label support in metric_find_query for label values

* use the same regex to check label values

* no need to escape

* support series endpoint

* support series endpoint

* support series endpoint

* support series endpoint

* fix tests

* fix extracting labels from labelValuesQuery

* show explanation with right syntax

* support utf8 metrics and labels
This commit is contained in:
ismail simsek
2025-01-16 16:50:35 +01:00
committed by GitHub
parent 029edcb6be
commit 106af5d0ee
2 changed files with 64 additions and 4 deletions

View File

@ -54,6 +54,49 @@ describe('buildSelector()', () => {
];
expect(buildSelector(labels)).toEqual('foo{bar="baz"}');
});
describe('utf8 support', () => {
it('metric selector with utf8 metric', () => {
const labels: SelectableLabel[] = [
{ name: '__name__', selected: true, values: [{ name: 'utf8.metric', selected: true }] },
];
expect(buildSelector(labels)).toEqual('{"utf8.metric"}');
});
it('metric selector with utf8 labels', () => {
const labels: SelectableLabel[] = [
{ name: '__name__', selected: true, values: [{ name: 'foo', selected: true }] },
{ name: 'utf8.label', selected: true, values: [{ name: 'baz', selected: true }] },
];
expect(buildSelector(labels)).toEqual('foo{"utf8.label"="baz"}');
});
it('metric selector with utf8 labels and metrics', () => {
const labels: SelectableLabel[] = [
{ name: '__name__', selected: true, values: [{ name: 'utf8.metric', selected: true }] },
{ name: 'utf8.label', selected: true, values: [{ name: 'baz', selected: true }] },
];
expect(buildSelector(labels)).toEqual('{"utf8.metric","utf8.label"="baz"}');
});
it('metric selector with utf8 metric and with utf8/non-utf8 labels', () => {
const labels: SelectableLabel[] = [
{ name: '__name__', selected: true, values: [{ name: 'utf8.metric', selected: true }] },
{ name: 'utf8.label', selected: true, values: [{ name: 'uuu', selected: true }] },
{ name: 'bar', selected: true, values: [{ name: 'baz', selected: true }] },
];
expect(buildSelector(labels)).toEqual('{"utf8.metric","utf8.label"="uuu",bar="baz"}');
});
it('metric selector with non-utf8 metric with utf8/non-utf8 labels', () => {
const labels: SelectableLabel[] = [
{ name: '__name__', selected: true, values: [{ name: 'foo', selected: true }] },
{ name: 'utf8.label', selected: true, values: [{ name: 'uuu', selected: true }] },
{ name: 'bar', selected: true, values: [{ name: 'baz', selected: true }] },
];
expect(buildSelector(labels)).toEqual('foo{"utf8.label"="uuu",bar="baz"}');
});
});
});
describe('facetLabels()', () => {

View File

@ -19,6 +19,7 @@ import {
import PromQlLanguageProvider from '../language_provider';
import { escapeLabelValueInExactSelector, escapeLabelValueInRegexSelector } from '../language_utils';
import { isValidLegacyName, utf8Support } from '../utf8_support';
// Hard limit on labels to render
const EMPTY_SELECTOR = '{}';
@ -68,22 +69,38 @@ export interface SelectableLabel {
export function buildSelector(labels: SelectableLabel[]): string {
let singleMetric = '';
const selectedLabels = [];
const selectedLabels: string[] = [];
for (const label of labels) {
if ((label.name === METRIC_LABEL || label.selected) && label.values && label.values.length > 0) {
const selectedValues = label.values.filter((value) => value.selected).map((value) => value.name);
if (selectedValues.length > 1) {
selectedLabels.push(`${label.name}=~"${selectedValues.map(escapeLabelValueInRegexSelector).join('|')}"`);
selectedLabels.push(
`${utf8Support(label.name)}=~"${selectedValues.map(escapeLabelValueInRegexSelector).join('|')}"`
);
} else if (selectedValues.length === 1) {
if (label.name === METRIC_LABEL) {
singleMetric = selectedValues[0];
} else {
selectedLabels.push(`${label.name}="${escapeLabelValueInExactSelector(selectedValues[0])}"`);
selectedLabels.push(`${utf8Support(label.name)}="${escapeLabelValueInExactSelector(selectedValues[0])}"`);
}
}
}
}
return [singleMetric, '{', selectedLabels.join(','), '}'].join('');
const selectorParts: string[] = [];
const isLegacyName = singleMetric === '' || isValidLegacyName(singleMetric);
if (isLegacyName) {
selectorParts.push(singleMetric, '{');
} else {
selectorParts.push('{', `"${singleMetric}"`);
if (selectedLabels.length > 0) {
selectorParts.push(',');
}
}
selectorParts.push(selectedLabels.join(','), '}');
return selectorParts.join('');
}
export function facetLabels(