diff --git a/app/vmui/packages/vmui/src/api/types.ts b/app/vmui/packages/vmui/src/api/types.ts index c495c829e..1a7cdb27c 100644 --- a/app/vmui/packages/vmui/src/api/types.ts +++ b/app/vmui/packages/vmui/src/api/types.ts @@ -15,7 +15,7 @@ export interface InstantMetricResult extends MetricBase { values?: [number, string][] } -export interface RawMetricResult extends MetricBase { +export interface ExportMetricResult extends MetricBase { values: number[]; timestamps: number[]; } diff --git a/app/vmui/packages/vmui/src/components/Views/GraphView/GraphView.tsx b/app/vmui/packages/vmui/src/components/Views/GraphView/GraphView.tsx index 05006a58e..a7e5aa309 100644 --- a/app/vmui/packages/vmui/src/components/Views/GraphView/GraphView.tsx +++ b/app/vmui/packages/vmui/src/components/Views/GraphView/GraphView.tsx @@ -180,7 +180,7 @@ const GraphView: FC = ({ if (isAnomalyView) { setHideSeries(legend.map(s => s.label || "").slice(1)); } - }, [data, timezone, isHistogram]); + }, [data, timezone, isHistogram, currentStep]); useEffect(() => { const tempLegend: LegendItemType[] = []; diff --git a/app/vmui/packages/vmui/src/pages/RawQueryPage/hooks/useFetchExport.ts b/app/vmui/packages/vmui/src/pages/RawQueryPage/hooks/useFetchExport.ts index d0f694dc7..8d9c61eb2 100644 --- a/app/vmui/packages/vmui/src/pages/RawQueryPage/hooks/useFetchExport.ts +++ b/app/vmui/packages/vmui/src/pages/RawQueryPage/hooks/useFetchExport.ts @@ -1,5 +1,5 @@ import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from "preact/compat"; -import { MetricBase, MetricResult, RawMetricResult } from "../../../api/types"; +import { MetricBase, MetricResult, ExportMetricResult } from "../../../api/types"; import { ErrorTypes, SeriesLimits } from "../../../types"; import { useQueryState } from "../../../state/query/QueryStateContext"; import { useTimeState } from "../../../state/time/TimeStateContext"; @@ -24,7 +24,7 @@ interface FetchQueryReturn { abortFetch: () => void } -const parseLineToJSON = (line: string): RawMetricResult | null => { +const parseLineToJSON = (line: string): ExportMetricResult | null => { try { return JSON.parse(line); } catch (e) { @@ -74,6 +74,7 @@ export const useFetchExport = ({ hideQuery, showAllSeries }: FetchQueryParams): try { const tempData: MetricBase[] = []; const seriesLimit = showAllSeries ? Infinity : +stateSeriesLimits[displayType] || Infinity; + console.log(+stateSeriesLimits[displayType]); let counter = 1; let totalLength = 0; @@ -97,14 +98,16 @@ export const useFetchExport = ({ hideQuery, showAllSeries }: FetchQueryParams): setQueryErrors(prev => [...prev, ""]); const freeTempSize = seriesLimit - tempData.length; const lines = text.split("\n").filter(line => line); - const linesLimited = lines.slice(0, freeTempSize); - const responseData = linesLimited.map(parseLineToJSON).filter(line => line) as RawMetricResult[]; - const metricResult = responseData.map((d: RawMetricResult) => ({ - group: counter, - metric: d.metric, - values: d.values.map((value, index) => [(d.timestamps[index]/1000), value]), - })); - tempData.push(...metricResult); + const lineLimited = lines.slice(0, freeTempSize).sort(); + lineLimited.forEach((line: string) => { + const jsonLine = parseLineToJSON(line); + if (!jsonLine) return; + tempData.push({ + group: counter, + metric: jsonLine.metric, + values: jsonLine.values.map((value, index) => [(jsonLine.timestamps[index]/1000), value]), + } as MetricBase); + }); totalLength += lines.length; } @@ -130,12 +133,11 @@ export const useFetchExport = ({ hideQuery, showAllSeries }: FetchQueryParams): useEffect(() => { if (!fetchUrl?.length) return; - fetchData({ - fetchUrl, - stateSeriesLimits, - showAllSeries, - }); - return () => abortControllerRef.current?.abort(); + const timer = setTimeout(fetchData, 400, { fetchUrl, stateSeriesLimits, showAllSeries }); + return () => { + abortControllerRef.current?.abort(); + clearTimeout(timer); + }; }, [fetchUrl, stateSeriesLimits, showAllSeries]); return { diff --git a/app/vmui/packages/vmui/src/pages/RawQueryPage/index.tsx b/app/vmui/packages/vmui/src/pages/RawQueryPage/index.tsx index d9c541209..9328adc24 100644 --- a/app/vmui/packages/vmui/src/pages/RawQueryPage/index.tsx +++ b/app/vmui/packages/vmui/src/pages/RawQueryPage/index.tsx @@ -81,9 +81,13 @@ const RawQueryPage: FC = () => {

This page provides a dedicated view for querying and displaying raw data directly from VictoriaMetrics. - Users often assume that the Query + Users often assume that the Query API returns data exactly as stored, but data samples and timestamps may be modified by the API. For more details, see How to export data in JSON line format diff --git a/app/vmui/packages/vmui/src/utils/uplot/series.ts b/app/vmui/packages/vmui/src/utils/uplot/series.ts index f28bde4fa..c1f2489f9 100644 --- a/app/vmui/packages/vmui/src/utils/uplot/series.ts +++ b/app/vmui/packages/vmui/src/utils/uplot/series.ts @@ -185,7 +185,27 @@ const getPointsSeries = (metricInfo: ForecastMetricInfo | null): uPlotSeries.Poi if (isAnomalyMetric) { return { size: 8, width: 4, space: 0 }; } - return { size: 4.2, width: 1.4 }; + return { + size: 4, + width: 0, + show: true, + filter: filterPoints, + }; +}; + +const filterPoints = (self: uPlot, seriesIdx: number): number[] | null => { + const data = self.data[seriesIdx]; + const indices = []; + + for (let i = 0; i < data.length; i++) { + const prev = data[i - 1]; + const next = data[i + 1]; + if (prev === null && next === null) { + indices.push(i); + } + } + + return indices.length > 0 ? indices : null; }; type GetStrokeSeriesArgs = { diff --git a/docs/changelog/CHANGELOG.md b/docs/changelog/CHANGELOG.md index 8af46cf72..d42a6fca4 100644 --- a/docs/changelog/CHANGELOG.md +++ b/docs/changelog/CHANGELOG.md @@ -27,6 +27,7 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/). * BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert): properly set `group_name` and `file` fields for recording rules in `/api/v1/rules`. * BUGFIX: [Single-node VictoriaMetrics](https://docs.victoriametrics.com/) and `vmstorage` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): prevent panic when ingesting samples which are outisde of configured [retention filters](https://docs.victoriametrics.com/#retention-filters). This could happen when backfilling data with retention filters which exclude samples from the backfill range. * BUGFIX: [vmctl](https://docs.victoriametrics.com/vmctl/): fix issue with series matching for `vmctl vm-native` with `--vm-native-disable-per-metric-migration` flag enabled. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7309). +* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix rendering of isolated data points on the graph that are not connected to other points. ## [v1.105.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.105.0)