mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
vmui/logs: add spinner to bar chart (#6577)
Add a spinner to the bar chart https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6558 --------- Signed-off-by: hagen1778 <roman@victoriametrics.com> Co-authored-by: hagen1778 <roman@victoriametrics.com>
This commit is contained in:
parent
8e9f98e725
commit
662e026279
5 changed files with 24 additions and 24 deletions
|
@ -48,9 +48,8 @@ const ExploreLogs: FC = () => {
|
||||||
|
|
||||||
const newPeriod = getPeriod();
|
const newPeriod = getPeriod();
|
||||||
setPeriod(newPeriod);
|
setPeriod(newPeriod);
|
||||||
fetchLogs(newPeriod).then(() => {
|
fetchLogs(newPeriod);
|
||||||
fetchLogHits(newPeriod);
|
fetchLogHits(newPeriod);
|
||||||
}).catch(e => e);
|
|
||||||
|
|
||||||
setSearchParamsFromKeys( {
|
setSearchParamsFromKeys( {
|
||||||
query,
|
query,
|
||||||
|
@ -95,9 +94,10 @@ const ExploreLogs: FC = () => {
|
||||||
{error && <Alert variant="error">{error}</Alert>}
|
{error && <Alert variant="error">{error}</Alert>}
|
||||||
{!error && (
|
{!error && (
|
||||||
<ExploreLogsBarChart
|
<ExploreLogsBarChart
|
||||||
|
{...dataLogHits}
|
||||||
query={query}
|
query={query}
|
||||||
period={period}
|
period={period}
|
||||||
{...dataLogHits}
|
isLoading={isLoading ? false : dataLogHits.isLoading}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ExploreLogsBody
|
<ExploreLogsBody
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { AlignedData } from "uplot";
|
||||||
import BarHitsChart from "../../../components/Chart/BarHitsChart/BarHitsChart";
|
import BarHitsChart from "../../../components/Chart/BarHitsChart/BarHitsChart";
|
||||||
import Alert from "../../../components/Main/Alert/Alert";
|
import Alert from "../../../components/Main/Alert/Alert";
|
||||||
import { TimeParams } from "../../../types";
|
import { TimeParams } from "../../../types";
|
||||||
|
import Spinner from "../../../components/Main/Spinner/Spinner";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
query: string;
|
query: string;
|
||||||
|
@ -18,7 +19,7 @@ interface Props {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExploreLogsBarChart: FC<Props> = ({ logHits, period, error }) => {
|
const ExploreLogsBarChart: FC<Props> = ({ logHits, period, error, isLoading }) => {
|
||||||
const { isMobile } = useDeviceDetect();
|
const { isMobile } = useDeviceDetect();
|
||||||
const timeDispatch = useTimeDispatch();
|
const timeDispatch = useTimeDispatch();
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ const ExploreLogsBarChart: FC<Props> = ({ logHits, period, error }) => {
|
||||||
"vm-block_mobile": isMobile,
|
"vm-block_mobile": isMobile,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
{isLoading && <Spinner containerStyles={{ position: "absolute" }}/>}
|
||||||
{!error && noDataMessage && (
|
{!error && noDataMessage && (
|
||||||
<div className="vm-explore-logs-chart__empty">
|
<div className="vm-explore-logs-chart__empty">
|
||||||
<Alert variant="info">{noDataMessage}</Alert>
|
<Alert variant="info">{noDataMessage}</Alert>
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { LOGS_BARS_VIEW } from "../../../constants/logs";
|
||||||
|
|
||||||
export const useFetchLogHits = (server: string, query: string) => {
|
export const useFetchLogHits = (server: string, query: string) => {
|
||||||
const [logHits, setLogHits] = useState<LogHits[]>([]);
|
const [logHits, setLogHits] = useState<LogHits[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState<{[key: number]: boolean;}>([]);
|
||||||
const [error, setError] = useState<ErrorTypes | string>();
|
const [error, setError] = useState<ErrorTypes | string>();
|
||||||
const abortControllerRef = useRef(new AbortController());
|
const abortControllerRef = useRef(new AbortController());
|
||||||
|
|
||||||
|
@ -36,7 +36,8 @@ export const useFetchLogHits = (server: string, query: string) => {
|
||||||
abortControllerRef.current = new AbortController();
|
abortControllerRef.current = new AbortController();
|
||||||
const { signal } = abortControllerRef.current;
|
const { signal } = abortControllerRef.current;
|
||||||
|
|
||||||
setIsLoading(true);
|
const id = Date.now();
|
||||||
|
setIsLoading(prev => ({ ...prev, [id]: true }));
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -47,8 +48,8 @@ export const useFetchLogHits = (server: string, query: string) => {
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
setError(text);
|
setError(text);
|
||||||
setLogHits([]);
|
setLogHits([]);
|
||||||
setIsLoading(false);
|
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||||
return Promise.reject(new Error(text));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
@ -56,25 +57,22 @@ export const useFetchLogHits = (server: string, query: string) => {
|
||||||
if (!hits) {
|
if (!hits) {
|
||||||
const error = "Error: No 'hits' field in response";
|
const error = "Error: No 'hits' field in response";
|
||||||
setError(error);
|
setError(error);
|
||||||
return Promise.reject(new Error(error));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setLogHits(hits);
|
setLogHits(!hits ? [] : hits);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error && e.name !== "AbortError") {
|
if (e instanceof Error && e.name !== "AbortError") {
|
||||||
setError(String(e));
|
setError(String(e));
|
||||||
console.error(e);
|
console.error(e);
|
||||||
setLogHits([]);
|
setLogHits([]);
|
||||||
}
|
}
|
||||||
return Promise.reject(e);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
}
|
||||||
|
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||||
}, [url, query]);
|
}, [url, query]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
logHits,
|
logHits,
|
||||||
isLoading,
|
isLoading: Object.values(isLoading).some(s => s),
|
||||||
error,
|
error,
|
||||||
fetchLogHits,
|
fetchLogHits,
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@ import dayjs from "dayjs";
|
||||||
|
|
||||||
export const useFetchLogs = (server: string, query: string, limit: number) => {
|
export const useFetchLogs = (server: string, query: string, limit: number) => {
|
||||||
const [logs, setLogs] = useState<Logs[]>([]);
|
const [logs, setLogs] = useState<Logs[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState<{[key: number]: boolean;}>([]);
|
||||||
const [error, setError] = useState<ErrorTypes | string>();
|
const [error, setError] = useState<ErrorTypes | string>();
|
||||||
const abortControllerRef = useRef(new AbortController());
|
const abortControllerRef = useRef(new AbortController());
|
||||||
|
|
||||||
|
@ -39,7 +39,8 @@ export const useFetchLogs = (server: string, query: string, limit: number) => {
|
||||||
abortControllerRef.current = new AbortController();
|
abortControllerRef.current = new AbortController();
|
||||||
const { signal } = abortControllerRef.current;
|
const { signal } = abortControllerRef.current;
|
||||||
|
|
||||||
setIsLoading(true);
|
const id = Date.now();
|
||||||
|
setIsLoading(prev => ({ ...prev, [id]: true }));
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -50,8 +51,8 @@ export const useFetchLogs = (server: string, query: string, limit: number) => {
|
||||||
if (!response.ok || !response.body) {
|
if (!response.ok || !response.body) {
|
||||||
setError(text);
|
setError(text);
|
||||||
setLogs([]);
|
setLogs([]);
|
||||||
setIsLoading(false);
|
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||||
return Promise.reject(new Error(text));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const lines = text.split("\n").filter(line => line).slice(0, limit);
|
const lines = text.split("\n").filter(line => line).slice(0, limit);
|
||||||
|
@ -63,16 +64,13 @@ export const useFetchLogs = (server: string, query: string, limit: number) => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
setLogs([]);
|
setLogs([]);
|
||||||
}
|
}
|
||||||
return Promise.reject(e);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
}
|
||||||
setIsLoading(false);
|
setIsLoading(prev => ({ ...prev, [id]: false }));
|
||||||
}, [url, query, limit]);
|
}, [url, query, limit]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
logs,
|
logs,
|
||||||
isLoading,
|
isLoading: Object.values(isLoading).some(s => s),
|
||||||
error,
|
error,
|
||||||
fetchLogs,
|
fetchLogs,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
|
||||||
|
|
||||||
## tip
|
## tip
|
||||||
|
|
||||||
|
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): show a spinner on top of bar chart until user's request is finished. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6558).
|
||||||
|
|
||||||
## [v0.27.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.27.1-victorialogs)
|
## [v0.27.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.27.1-victorialogs)
|
||||||
|
|
||||||
Released at 2024-07-05
|
Released at 2024-07-05
|
||||||
|
|
Loading…
Reference in a new issue