mirror of
https://github.com/prometheus/prometheus.git
synced 2025-08-05 13:47:10 +02:00
UI: More inclusive metadata handling for _count/_sum/_bucket suffixes (#16910)
Although these suffixes always need to be removed before querying metadata for metrics that follow the Prometheus naming best practices, there can also be metrics that don't follow these naming practices and have these suffixes without being part of either a histogram or a summary metric. Fixes https://github.com/prometheus/prometheus/issues/16907 Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
f8b3fce845
commit
13b55ffc81
@ -128,13 +128,28 @@ const matchingCriteriaList = (
|
||||
const SelectorExplainView: FC<SelectorExplainViewProps> = ({ node }) => {
|
||||
const baseMetricName = node.name.replace(/(_count|_sum|_bucket)$/, "");
|
||||
const { lookbackDelta } = useSettings();
|
||||
const { data: metricMeta } = useSuspenseAPIQuery<MetadataResult>({
|
||||
|
||||
// Try to get metadata for the full unchanged metric name first.
|
||||
const { data: fullMetricMeta } = useSuspenseAPIQuery<MetadataResult>({
|
||||
path: `/metadata`,
|
||||
params: {
|
||||
metric: node.name,
|
||||
},
|
||||
});
|
||||
|
||||
// Also get prefix-stripped metric metadata in case the metadata only exists for
|
||||
// the histogram / summary base metric name.
|
||||
const { data: baseMetricMeta } = useSuspenseAPIQuery<MetadataResult>({
|
||||
path: `/metadata`,
|
||||
params: {
|
||||
metric: baseMetricName,
|
||||
},
|
||||
});
|
||||
|
||||
// Determine which metadata to use.
|
||||
const metricMeta =
|
||||
fullMetricMeta.data[node.name] ?? baseMetricMeta.data[baseMetricName];
|
||||
|
||||
return (
|
||||
<Card withBorder>
|
||||
<Text fz="lg" fw={600} mb="md">
|
||||
@ -142,17 +157,13 @@ const SelectorExplainView: FC<SelectorExplainViewProps> = ({ node }) => {
|
||||
selector
|
||||
</Text>
|
||||
<Text fz="sm">
|
||||
{metricMeta.data === undefined ||
|
||||
metricMeta.data[baseMetricName] === undefined ||
|
||||
metricMeta.data[baseMetricName].length < 1 ? (
|
||||
{metricMeta === undefined || metricMeta.length < 1 ? (
|
||||
<>No metric metadata found.</>
|
||||
) : (
|
||||
<>
|
||||
<strong>Metric help</strong>:{" "}
|
||||
{metricMeta.data[baseMetricName][0].help}
|
||||
<strong>Metric help</strong>: {metricMeta[0].help}
|
||||
<br />
|
||||
<strong>Metric type</strong>:{" "}
|
||||
{metricMeta.data[baseMetricName][0].type}
|
||||
<strong>Metric type</strong>: {metricMeta[0].type}
|
||||
</>
|
||||
)}
|
||||
</Text>
|
||||
@ -161,7 +172,8 @@ const SelectorExplainView: FC<SelectorExplainViewProps> = ({ node }) => {
|
||||
{node.type === nodeType.vectorSelector ? (
|
||||
<>
|
||||
This node selects the latest (non-stale) sample value within the
|
||||
last <span className="promql-code promql-duration">{lookbackDelta}</span>
|
||||
last{" "}
|
||||
<span className="promql-code promql-duration">{lookbackDelta}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
@ -1,11 +1,23 @@
|
||||
import { FC, useMemo, useState } from "react";
|
||||
import { useSuspenseAPIQuery } from "../../../api/api";
|
||||
import { MetadataResult } from "../../../api/responseTypes/metadata";
|
||||
import { ActionIcon, CopyButton, Group, Stack, Table, TextInput } from "@mantine/core";
|
||||
import {
|
||||
ActionIcon,
|
||||
CopyButton,
|
||||
Group,
|
||||
Stack,
|
||||
Table,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import React from "react";
|
||||
import { Fuzzy } from "@nexucis/fuzzy";
|
||||
import sanitizeHTML from "sanitize-html";
|
||||
import { IconCheck, IconCodePlus, IconCopy, IconZoomCode } from "@tabler/icons-react";
|
||||
import {
|
||||
IconCheck,
|
||||
IconCodePlus,
|
||||
IconCopy,
|
||||
IconZoomCode,
|
||||
} from "@tabler/icons-react";
|
||||
import LabelsExplorer from "./LabelsExplorer";
|
||||
import { useDebouncedValue } from "@mantine/hooks";
|
||||
import classes from "./MetricsExplorer.module.css";
|
||||
@ -55,10 +67,17 @@ const MetricsExplorer: FC<MetricsExplorerProps> = ({
|
||||
return getSearchMatches(debouncedFilterText, metricNames);
|
||||
}, [debouncedFilterText, metricNames]);
|
||||
|
||||
const getMeta = (m: string) =>
|
||||
data.data[m.replace(/(_count|_sum|_bucket)$/, "")] || [
|
||||
{ help: "unknown", type: "unknown", unit: "unknown" },
|
||||
];
|
||||
const getMeta = (m: string) => {
|
||||
return (
|
||||
// First check if the full metric name has metadata (even if it has one of the
|
||||
// histogram/summary suffixes, it may be a metric that is not following naming
|
||||
// conventions, see https://github.com/prometheus/prometheus/issues/16907).
|
||||
data.data[m] ??
|
||||
data.data[m.replace(/(_count|_sum|_bucket)$/, "")] ?? [
|
||||
{ help: "unknown", type: "unknown", unit: "unknown" },
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
if (selectedMetric !== null) {
|
||||
return (
|
||||
|
@ -664,9 +664,11 @@ export class HybridComplete implements CompleteStrategy {
|
||||
.then((metricMetadata) => {
|
||||
if (metricMetadata) {
|
||||
for (const [metricName, node] of metricCompletion) {
|
||||
// For histograms and summaries, the metadata is only exposed for the base metric name,
|
||||
// not separately for the _count, _sum, and _bucket time series.
|
||||
const metadata = metricMetadata[metricName.replace(/(_count|_sum|_bucket)$/, '')];
|
||||
// First check if the full metric name has metadata (even if it has one of the
|
||||
// histogram/summary suffixes, it may be a metric that is not following naming
|
||||
// conventions, see https://github.com/prometheus/prometheus/issues/16907).
|
||||
// Then fall back to the base metric name if full metadata doesn't exist.
|
||||
const metadata = metricMetadata[metricName] ?? metricMetadata[metricName.replace(/(_count|_sum|_bucket)$/, '')];
|
||||
if (metadata) {
|
||||
if (metadata.length > 1) {
|
||||
// it means the metricName has different possible helper and type
|
||||
|
Loading…
Reference in New Issue
Block a user