mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-20 15:16:42 +00:00
fix: change columns for Top Queries (#3093)
This commit is contained in:
parent
c48ff746c6
commit
b5f4060520
5 changed files with 57 additions and 33 deletions
|
@ -126,18 +126,35 @@ const TopQueries: FC = () => {
|
|||
<Box>
|
||||
<TopQueryPanel
|
||||
rows={data.topByCount}
|
||||
title={"Top by count"}
|
||||
description={"The most frequently executed queries"}
|
||||
title={"Most frequently executed queries"}
|
||||
columns={[
|
||||
{key: "query"},
|
||||
{key: "timeRangeHours", title: "time range, hours"},
|
||||
{key: "count"}
|
||||
]}
|
||||
/>
|
||||
<TopQueryPanel
|
||||
rows={data.topByAvgDuration}
|
||||
title={"Top by avg duration"}
|
||||
description={"Queries that took the most average execution time"}
|
||||
title={"Most heavy queries"}
|
||||
// columns={["query", "avgDurationSeconds", "timeRangeHours", "count"]}
|
||||
columns={[
|
||||
{key: "query"},
|
||||
{key: "avgDurationSeconds", title: "avg duration, seconds"},
|
||||
{key: "timeRangeHours", title: "time range, hours"},
|
||||
{key: "count"}
|
||||
]}
|
||||
defaultOrderBy={"avgDurationSeconds"}
|
||||
/>
|
||||
<TopQueryPanel
|
||||
rows={data.topBySumDuration}
|
||||
title={"Top by sum duration"}
|
||||
description={"Queries that took the highest summary execution time"}
|
||||
title={"Queries with most summary time to execute"}
|
||||
columns={[
|
||||
{key: "query"},
|
||||
{key: "sumDurationSeconds", title: "sum duration, seconds"},
|
||||
{key: "timeRangeHours", title: "time range, hours"},
|
||||
{key: "count"}
|
||||
]}
|
||||
defaultOrderBy={"sumDurationSeconds"}
|
||||
/>
|
||||
</Box>
|
||||
</>)}
|
||||
|
|
|
@ -2,8 +2,6 @@ import React, {FC, useState} from "react";
|
|||
import Box from "@mui/material/Box";
|
||||
import {TopQuery} from "../../../types";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import InfoIcon from "@mui/icons-material/Info";
|
||||
import Accordion from "@mui/material/Accordion";
|
||||
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
@ -15,14 +13,15 @@ import CodeIcon from "@mui/icons-material/Code";
|
|||
import TopQueryTable from "../TopQueryTable/TopQueryTable";
|
||||
import JsonView from "../../CustomPanel/Views/JsonView";
|
||||
|
||||
interface TopQueryPanelProps {
|
||||
export interface TopQueryPanelProps {
|
||||
rows: TopQuery[],
|
||||
title: string,
|
||||
description: string
|
||||
title?: string,
|
||||
columns: {title?: string, key: (keyof TopQuery)}[],
|
||||
defaultOrderBy?: keyof TopQuery,
|
||||
}
|
||||
const tabs = ["table", "JSON"];
|
||||
|
||||
const TopQueryPanel: FC<TopQueryPanelProps> = ({rows, title, description}) => {
|
||||
const TopQueryPanel: FC<TopQueryPanelProps> = ({rows, title, columns, defaultOrderBy}) => {
|
||||
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
|
||||
|
@ -52,9 +51,6 @@ const TopQueryPanel: FC<TopQueryPanelProps> = ({rows, title, description}) => {
|
|||
}}
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
>
|
||||
<Tooltip arrow title={description}>
|
||||
<InfoIcon color="info" sx={{mr: 1}}/>
|
||||
</Tooltip>
|
||||
<Typography variant="h6" component="h6">
|
||||
{title}
|
||||
</Typography>
|
||||
|
@ -79,7 +75,7 @@ const TopQueryPanel: FC<TopQueryPanelProps> = ({rows, title, description}) => {
|
|||
)}
|
||||
</Tabs>
|
||||
</Box>
|
||||
{activeTab === 0 && <TopQueryTable rows={rows}/>}
|
||||
{activeTab === 0 && <TopQueryTable rows={rows} columns={columns} defaultOrderBy={defaultOrderBy}/>}
|
||||
{activeTab === 1 && <Box m={2}><JsonView data={rows} /></Box>}
|
||||
</Box>
|
||||
</AccordionDetails>
|
||||
|
|
|
@ -8,27 +8,22 @@ import TableBody from "@mui/material/TableBody";
|
|||
import TableSortLabel from "@mui/material/TableSortLabel";
|
||||
import {TopQuery} from "../../../types";
|
||||
import {getComparator, stableSort} from "../../Table/helpers";
|
||||
import {TopQueryPanelProps} from "../TopQueryPanel/TopQueryPanel";
|
||||
|
||||
interface TopQueryTableProps {
|
||||
rows: TopQuery[],
|
||||
}
|
||||
type ColumnKeys = keyof TopQuery;
|
||||
const columns: ColumnKeys[] = ["query", "timeRangeSeconds", "avgDurationSeconds", "count", "accountID", "projectID"];
|
||||
const TopQueryTable:FC<TopQueryPanelProps> = ({rows, columns, defaultOrderBy}) => {
|
||||
|
||||
const TopQueryTable:FC<TopQueryTableProps> = ({rows}) => {
|
||||
|
||||
const [orderBy, setOrderBy] = useState("count");
|
||||
const [orderBy, setOrderBy] = useState<keyof TopQuery>(defaultOrderBy || "count");
|
||||
const [orderDir, setOrderDir] = useState<"asc" | "desc">("desc");
|
||||
|
||||
const sortedList = useMemo(() => stableSort(rows as [], getComparator(orderDir, orderBy)),
|
||||
[rows, orderBy, orderDir]);
|
||||
|
||||
const onSortHandler = (key: string) => {
|
||||
const onSortHandler = (key: keyof TopQuery) => {
|
||||
setOrderDir((prev) => prev === "asc" && orderBy === key ? "desc" : "asc");
|
||||
setOrderBy(key);
|
||||
};
|
||||
|
||||
const createSortHandler = (col: string) => () => {
|
||||
const createSortHandler = (col: keyof TopQuery) => () => {
|
||||
onSortHandler(col);
|
||||
};
|
||||
|
||||
|
@ -40,14 +35,18 @@ const TopQueryTable:FC<TopQueryTableProps> = ({rows}) => {
|
|||
<TableHead>
|
||||
<TableRow>
|
||||
{columns.map((col) => (
|
||||
<TableCell key={col} sx={{ borderBottomColor: "primary.light" }}>
|
||||
<TableCell
|
||||
key={col.key}
|
||||
style={{width: "100%"}}
|
||||
sx={{borderBottomColor: "primary.light", whiteSpace: "nowrap"}}
|
||||
>
|
||||
<TableSortLabel
|
||||
active={orderBy === col}
|
||||
active={orderBy === col.key}
|
||||
direction={orderDir}
|
||||
id={col}
|
||||
onClick={createSortHandler(col)}
|
||||
id={col.key}
|
||||
onClick={createSortHandler(col.key)}
|
||||
>
|
||||
{col}
|
||||
{col.title || col.key}
|
||||
</TableSortLabel>
|
||||
</TableCell>
|
||||
))}
|
||||
|
@ -58,13 +57,13 @@ const TopQueryTable:FC<TopQueryTableProps> = ({rows}) => {
|
|||
<TableRow key={rowIndex}>
|
||||
{columns.map((col) => (
|
||||
<TableCell
|
||||
key={col}
|
||||
key={col.key}
|
||||
sx={{
|
||||
borderBottom: rowIndex === rows.length - 1 ? "none" : "",
|
||||
borderBottomColor: "primary.light"
|
||||
}}
|
||||
>
|
||||
{row[col] || "-"}
|
||||
{row[col.key] || "-"}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
|
|
|
@ -26,6 +26,16 @@ export const useFetchTopQueries = () => {
|
|||
try {
|
||||
const response = await fetch(fetchUrl);
|
||||
const resp = await response.json();
|
||||
if (response.ok) {
|
||||
const list = ["topByAvgDuration", "topByCount", "topBySumDuration"] as (keyof TopQueriesData)[];
|
||||
list.forEach(key => {
|
||||
const target = resp[key];
|
||||
if (Array.isArray(target)) {
|
||||
target.forEach(t => t.timeRangeHours = +(t.timeRangeSeconds/3600).toFixed(2));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setData(response.ok ? resp : null);
|
||||
setError(String(resp.error || ""));
|
||||
} catch (e) {
|
||||
|
|
|
@ -77,6 +77,8 @@ export interface TopQuery {
|
|||
projectID: number
|
||||
query: string
|
||||
timeRangeSeconds: number
|
||||
sumDurationSeconds: number
|
||||
timeRangeHours: number
|
||||
}
|
||||
|
||||
export interface TopQueryStats {
|
||||
|
|
Loading…
Reference in a new issue