From d23872ef30206654076bd4269b32c9b39ba915a6 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Sun, 8 Sep 2024 21:11:06 +0200 Subject: [PATCH] Graph range vector selectors as instant vector selectors with notice Signed-off-by: Julius Volz --- web/ui/mantine-ui/src/pages/query/Graph.tsx | 84 +++++++++++++------ .../mantine-ui/src/pages/query/QueryPanel.tsx | 1 + 2 files changed, 59 insertions(+), 26 deletions(-) diff --git a/web/ui/mantine-ui/src/pages/query/Graph.tsx b/web/ui/mantine-ui/src/pages/query/Graph.tsx index 3fc9a6c51..d037546cf 100644 --- a/web/ui/mantine-ui/src/pages/query/Graph.tsx +++ b/web/ui/mantine-ui/src/pages/query/Graph.tsx @@ -1,5 +1,5 @@ import { FC, useEffect, useId, useState } from "react"; -import { Alert, Skeleton, Box, LoadingOverlay } from "@mantine/core"; +import { Alert, Skeleton, Box, LoadingOverlay, Stack } from "@mantine/core"; import { IconAlertTriangle, IconInfoCircle } from "@tabler/icons-react"; import { RangeQueryResult } from "../../api/responseTypes/query"; import { SuccessAPIResponse, useAPIQuery } from "../../api/api"; @@ -13,9 +13,12 @@ import "uplot/dist/uPlot.min.css"; import "./uplot.css"; import { useElementSize } from "@mantine/hooks"; import UPlotChart, { UPlotChartRange } from "./UPlotChart"; +import ASTNode, { nodeType } from "../../promql/ast"; +import serializeNode from "../../promql/serialize"; export interface GraphProps { expr: string; + node: ASTNode | null; endTime: number | null; range: number; resolution: GraphResolution; @@ -27,6 +30,7 @@ export interface GraphProps { const Graph: FC = ({ expr, + node, endTime, range, resolution, @@ -38,6 +42,22 @@ const Graph: FC = ({ const { ref, width } = useElementSize(); const [rerender, setRerender] = useState(true); + const effectiveExpr = + node === null + ? expr + : serializeNode( + node.type === nodeType.matrixSelector + ? { + type: nodeType.vectorSelector, + name: node.name, + matchers: node.matchers, + offset: node.offset, + timestamp: node.timestamp, + startOrEnd: node.startOrEnd, + } + : node + ); + const effectiveEndTime = (endTime !== null ? endTime : Date.now()) / 1000; const startTime = effectiveEndTime - range / 1000; const effectiveResolution = getEffectiveResolution(resolution, range) / 1000; @@ -47,12 +67,12 @@ const Graph: FC = ({ key: [useId()], path: "/query_range", params: { - query: expr, + query: effectiveExpr, step: effectiveResolution.toString(), start: startTime.toString(), end: effectiveEndTime.toString(), }, - enabled: expr !== "", + enabled: effectiveExpr !== "", }); // Bundle the chart data and the displayed range together. This has two purposes: @@ -82,8 +102,8 @@ const Graph: FC = ({ // Re-execute the query when the user presses Enter (or hits the Execute button). useEffect(() => { - expr !== "" && refetch(); - }, [retriggerIdx, refetch, expr, endTime, range, resolution]); + effectiveExpr !== "" && refetch(); + }, [retriggerIdx, refetch, effectiveExpr, endTime, range, resolution]); // The useElementSize hook above only gets a valid size on the second render, so this // is a workaround to make the component render twice after mount. @@ -133,27 +153,39 @@ const Graph: FC = ({ } return ( - - , - // }} - // styles={{ loader: { width: "100%", height: "100%" } }} - /> - - + + {node !== null && node.type === nodeType.matrixSelector && ( + } + > + Note: Range vector selectors can't be graphed, so + graphing the equivalent instant vector selector instead. + + )} + + , + // }} + // styles={{ loader: { width: "100%", height: "100%" } }} + /> + + + ); }; diff --git a/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx b/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx index 09deb95e3..a17231182 100644 --- a/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx +++ b/web/ui/mantine-ui/src/pages/query/QueryPanel.tsx @@ -296,6 +296,7 @@ const QueryPanel: FC = ({ idx, metricNames }) => {