mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
vmui/logs: fix display of hits chart (#7167)
### Describe Your Changes Fixed the display of hits chart in VictoriaLogs. See #7133 ### Checklist The following checks are **mandatory**: - [ ] My change adheres [VictoriaMetrics contributing guidelines](https://docs.victoriametrics.com/contributing/).
This commit is contained in:
parent
064b9a6314
commit
36a86c3aaf
4 changed files with 48 additions and 20 deletions
|
@ -1,4 +1,4 @@
|
|||
import React, { FC, useMemo } from "preact/compat";
|
||||
import React, { FC, useCallback, useMemo } from "preact/compat";
|
||||
import "./style.scss";
|
||||
import useDeviceDetect from "../../../hooks/useDeviceDetect";
|
||||
import classNames from "classnames";
|
||||
|
@ -10,6 +10,7 @@ import BarHitsChart from "../../../components/Chart/BarHitsChart/BarHitsChart";
|
|||
import Alert from "../../../components/Main/Alert/Alert";
|
||||
import { TimeParams } from "../../../types";
|
||||
import LineLoader from "../../../components/Main/LineLoader/LineLoader";
|
||||
import { getHitsTimeParams } from "../../../utils/logs";
|
||||
|
||||
interface Props {
|
||||
query: string;
|
||||
|
@ -24,26 +25,43 @@ const ExploreLogsBarChart: FC<Props> = ({ logHits, period, error, isLoading, onA
|
|||
const { isMobile } = useDeviceDetect();
|
||||
const timeDispatch = useTimeDispatch();
|
||||
|
||||
const getXAxis = (timestamps: string[]): number[] => {
|
||||
return (timestamps.map(t => t ? dayjs(t).unix() : null)
|
||||
.filter(Boolean) as number[])
|
||||
.sort((a, b) => a - b);
|
||||
};
|
||||
|
||||
const getYAxes = (logHits: LogHits[], timestamps: string[]) => {
|
||||
const getYAxes = (logHits: LogHits[], timestamps: number[]) => {
|
||||
return logHits.map(hits => {
|
||||
return timestamps.map(t => {
|
||||
const index = hits.timestamps.findIndex(ts => ts === t);
|
||||
return index === -1 ? null : hits.values[index] || null;
|
||||
const timestampValueMap = new Map();
|
||||
hits.timestamps.forEach((ts, idx) => {
|
||||
const unixTime = dayjs(ts).unix();
|
||||
timestampValueMap.set(unixTime, hits.values[idx] || null);
|
||||
});
|
||||
|
||||
return timestamps.map(t => timestampValueMap.get(t) || null);
|
||||
});
|
||||
};
|
||||
|
||||
const generateTimestamps = useCallback((date: dayjs.Dayjs) => {
|
||||
const result: number[] = [];
|
||||
const { start, end, step } = getHitsTimeParams(period);
|
||||
const stepsToFirstTimestamp = Math.ceil(start.diff(date, "milliseconds") / step);
|
||||
let firstTimestamp = date.add(stepsToFirstTimestamp * step, "milliseconds");
|
||||
|
||||
// If the first timestamp is before 'start', set it to 'start'
|
||||
if (firstTimestamp.isBefore(start)) {
|
||||
firstTimestamp = start.clone();
|
||||
}
|
||||
|
||||
// Calculate the total number of steps from 'firstTimestamp' to 'end'
|
||||
const totalSteps = Math.floor(end.diff(firstTimestamp, "milliseconds") / step);
|
||||
|
||||
for (let i = 0; i <= totalSteps; i++) {
|
||||
result.push(firstTimestamp.add(i * step, "milliseconds").unix());
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [period]);
|
||||
|
||||
const data = useMemo(() => {
|
||||
if (!logHits.length) return [[], []] as AlignedData;
|
||||
const timestamps = Array.from(new Set(logHits.map(l => l.timestamps).flat()));
|
||||
const xAxis = getXAxis(timestamps);
|
||||
const yAxes = getYAxes(logHits, timestamps);
|
||||
const xAxis = generateTimestamps(dayjs(logHits[0].timestamps[0]));
|
||||
const yAxes = getYAxes(logHits, xAxis);
|
||||
return [xAxis, ...yAxes] as AlignedData;
|
||||
}, [logHits]);
|
||||
|
||||
|
|
|
@ -2,9 +2,8 @@ import { useCallback, useMemo, useRef, useState } from "preact/compat";
|
|||
import { getLogHitsUrl } from "../../../api/logs";
|
||||
import { ErrorTypes, TimeParams } from "../../../types";
|
||||
import { LogHits } from "../../../api/types";
|
||||
import dayjs from "dayjs";
|
||||
import { LOGS_BARS_VIEW } from "../../../constants/logs";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { getHitsTimeParams } from "../../../utils/logs";
|
||||
|
||||
export const useFetchLogHits = (server: string, query: string) => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
@ -17,10 +16,7 @@ export const useFetchLogHits = (server: string, query: string) => {
|
|||
const url = useMemo(() => getLogHitsUrl(server), [server]);
|
||||
|
||||
const getOptions = (query: string, period: TimeParams, signal: AbortSignal) => {
|
||||
const start = dayjs(period.start * 1000);
|
||||
const end = dayjs(period.end * 1000);
|
||||
const totalSeconds = end.diff(start, "milliseconds");
|
||||
const step = Math.ceil(totalSeconds / LOGS_BARS_VIEW) || 1;
|
||||
const { start, end, step } = getHitsTimeParams(period);
|
||||
|
||||
return {
|
||||
signal,
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
import { TimeParams } from "../types";
|
||||
import dayjs from "dayjs";
|
||||
import { LOGS_BARS_VIEW } from "../constants/logs";
|
||||
|
||||
export const getStreamPairs = (value: string): string[] => {
|
||||
const pairs = /^{.+}$/.test(value) ? value.slice(1, -1).split(",") : [value];
|
||||
return pairs.filter(Boolean);
|
||||
};
|
||||
|
||||
export const getHitsTimeParams = (period: TimeParams) => {
|
||||
const start = dayjs(period.start * 1000);
|
||||
const end = dayjs(period.end * 1000);
|
||||
const totalSeconds = end.diff(start, "milliseconds");
|
||||
const step = Math.ceil(totalSeconds / LOGS_BARS_VIEW) || 1;
|
||||
return { start, end, step };
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
|
|||
* FEATURE: improve performance for [`top`](https://docs.victoriametrics.com/victorialogs/logsql/#top-pipe), [`uniq`](https://docs.victoriametrics.com/victorialogs/logsql/#uniq-pipe) and [`field_values`](https://docs.victoriametrics.com/victorialogs/logsql/#field_values-pipe) pipes on systems with many CPU cores when it is applied to [log fields](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model) with big number of unique values. For example, `_time:1d | top 5 (user_id)` should be executed much faster when `user_id` field contains millions of unique values.
|
||||
* FEATURE: improve performance for [`field_names` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#field_names-pipe) when it is applied to logs with hundreds of [log fields](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model).
|
||||
|
||||
* BUGFIX: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): fix display of hits chart. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7133).
|
||||
|
||||
## [v0.36.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.36.0-victorialogs)
|
||||
|
||||
Released at 2024-10-16
|
||||
|
|
Loading…
Reference in a new issue