From 64793ff5f043c85208dbeea22d59b71d2415aabf Mon Sep 17 00:00:00 2001 From: Yury Molodov Date: Fri, 27 Sep 2024 13:19:46 +0200 Subject: [PATCH] vmui/logs: improve graph usability (#7025) ### Describe Your Changes - Show the time range in the tooltip when hovering over staircase graphs. - Use bolder lines for staircase graphs. - Increase the number of steps on the staircase graph to 100. - Reduce the maximum width of the tooltip to 1/3 of the screen. - Insert only the label name under the cursor into the query input field when `Ctrl`-clicking the line legend. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6545#issuecomment-2336805237). ### Checklist The following checks are **mandatory**: - [ ] My change adheres [VictoriaMetrics contributing guidelines](https://docs.victoriametrics.com/contributing/). --------- Co-authored-by: Aliaksandr Valialkin --- .../BarHitsLegend/BarHitsLegend.tsx | 35 ++++++++++++++----- .../BarHitsChart/BarHitsLegend/style.scss | 31 ++++++++++++++-- .../BarHitsTooltip/BarHitsTooltip.tsx | 6 +++- .../BarHitsChart/hooks/useBarHitsOptions.ts | 6 ++-- .../components/Chart/ChartTooltip/style.scss | 1 + app/vmui/packages/vmui/src/constants/logs.ts | 2 +- .../pages/ExploreLogs/GroupLogs/GroupLogs.tsx | 7 ++-- app/vmui/packages/vmui/src/utils/logs.ts | 4 +++ docs/VictoriaLogs/CHANGELOG.md | 2 ++ 9 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 app/vmui/packages/vmui/src/utils/logs.ts diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegend.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegend.tsx index e4d82cc985..238d8a3a88 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegend.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/BarHitsLegend.tsx @@ -6,6 +6,7 @@ import classNames from "classnames"; import { MouseEvent } from "react"; import { isMacOs } from "../../../../utils/detect-device"; import Tooltip from "../../../Main/Tooltip/Tooltip"; +import { getStreamPairs } from "../../../../utils/logs"; interface Props { uPlotInst: uPlot; @@ -14,20 +15,26 @@ interface Props { const BarHitsLegend: FC = ({ uPlotInst, onApplyFilter }) => { const [series, setSeries] = useState([]); + const [pairs, setPairs] = useState([]); const updateSeries = useCallback(() => { const series = uPlotInst.series.filter(s => s.scale !== "x"); setSeries(series); + setPairs(series.map(s => getStreamPairs(s.label || ""))); }, [uPlotInst]); - const handleClick = (target: Series) => (e: MouseEvent) => { + const handleClickByValue = (value: string) => (e: MouseEvent) => { const metaKey = e.metaKey || e.ctrlKey; - if (!metaKey) { - target.show = !target.show; - } else { - onApplyFilter(target.label || ""); - } + if (!metaKey) return; + onApplyFilter(`{${value}}` || ""); + updateSeries(); + uPlotInst.redraw(); + }; + const handleClickByStream = (target: Series) => (e: MouseEvent) => { + const metaKey = e.metaKey || e.ctrlKey; + if (metaKey) return; + target.show = !target.show; updateSeries(); uPlotInst.redraw(); }; @@ -36,7 +43,7 @@ const BarHitsLegend: FC = ({ uPlotInst, onApplyFilter }) => { return (
- {series.map(s => ( + {series.map((s, i) => ( = ({ uPlotInst, onApplyFilter }) => { "vm-bar-hits-legend-item": true, "vm-bar-hits-legend-item_hide": !s.show, })} - onClick={handleClick(s)} + onClick={handleClickByStream(s)} >
string)?.()}` }} /> -
{s.label}
+
+ {pairs[i].map(value => ( + + {value} + + ))} +
))} diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/style.scss b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/style.scss index 77b912c5e5..def94e5370 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/style.scss +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsLegend/style.scss @@ -3,16 +3,16 @@ .vm-bar-hits-legend { display: flex; flex-wrap: wrap; - gap: 0; + gap: $padding-small; padding: 0 $padding-small $padding-small; &-item { display: grid; grid-template-columns: auto 1fr; align-items: center; - gap: 4px; + gap: $padding-small; font-size: 12px; - padding: $padding-small; + padding: 0 $padding-small; border-radius: $border-radius-small; cursor: pointer; transition: 0.2s; @@ -31,5 +31,30 @@ height: 14px; border: $color-background-block; } + + &-pairs { + display: flex; + gap: $padding-small; + + &__value { + padding: $padding-small 0; + + &:hover { + text-decoration: underline; + } + + &:after { + content: ","; + } + + &:last-child:after { + content: ""; + } + } + } + } + + &-info { + list-style-position: inside; } } diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsTooltip/BarHitsTooltip.tsx b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsTooltip/BarHitsTooltip.tsx index 7a9ce4269b..bf985d30a5 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsTooltip/BarHitsTooltip.tsx +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/BarHitsTooltip/BarHitsTooltip.tsx @@ -12,12 +12,16 @@ interface Props { focusDataIdx: number; } +const timeFormat = (ts: number) => dayjs(ts * 1000).tz().format(DATE_TIME_FORMAT); + const BarHitsTooltip: FC = ({ data, focusDataIdx, uPlotInst }) => { const tooltipRef = useRef(null); const tooltipData = useMemo(() => { const series = uPlotInst?.series || []; const [time, ...values] = data.map((d) => d[focusDataIdx] || 0); + const step = (data[0][1] - data[0][0]); + const timeNext = time + step; const tooltipItems = values.map((value, i) => { const targetSeries = series[i + 1]; @@ -41,7 +45,7 @@ const BarHitsTooltip: FC = ({ data, focusDataIdx, uPlotInst }) => { point, values: tooltipItems, total: tooltipItems.reduce((acc, item) => acc + item.value, 0), - timestamp: dayjs(time * 1000).tz().format(DATE_TIME_FORMAT), + timestamp: `${timeFormat(time)} - ${timeFormat(timeNext)}`, }; }, [focusDataIdx, uPlotInst, data]); diff --git a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts index ab699db3e8..68823c2abe 100644 --- a/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts +++ b/app/vmui/packages/vmui/src/components/Chart/BarHitsChart/hooks/useBarHitsOptions.ts @@ -19,8 +19,8 @@ const seriesColors = [ ]; const strokeWidth = { - [GRAPH_STYLES.BAR]: 0.8, - [GRAPH_STYLES.LINE_STEPPED]: 1.2, + [GRAPH_STYLES.BAR]: 1, + [GRAPH_STYLES.LINE_STEPPED]: 2, [GRAPH_STYLES.LINE]: 1.2, [GRAPH_STYLES.POINTS]: 0, }; @@ -82,7 +82,7 @@ const useBarHitsOptions = ({ cursor: { points: { width: (u, seriesIdx, size) => size / 4, - size: (u, seriesIdx) => (u.series?.[seriesIdx]?.points?.size || 1) * 2.5, + size: (u, seriesIdx) => (u.series?.[seriesIdx]?.points?.size || 1) * 1.5, stroke: (u, seriesIdx) => `${series?.[seriesIdx]?.stroke || "#ffffff"}`, fill: () => "#ffffff", }, diff --git a/app/vmui/packages/vmui/src/components/Chart/ChartTooltip/style.scss b/app/vmui/packages/vmui/src/components/Chart/ChartTooltip/style.scss index 02d533aa07..877d37b80d 100644 --- a/app/vmui/packages/vmui/src/components/Chart/ChartTooltip/style.scss +++ b/app/vmui/packages/vmui/src/components/Chart/ChartTooltip/style.scss @@ -29,6 +29,7 @@ $chart-tooltip-y: -1 * ($padding-global + $chart-tooltip-half-icon); white-space: pre-wrap; word-break: break-all; width: auto; + max-width: calc(100vw/3); } &_sticky { diff --git a/app/vmui/packages/vmui/src/constants/logs.ts b/app/vmui/packages/vmui/src/constants/logs.ts index 4ad19c3e19..24804e6ef1 100644 --- a/app/vmui/packages/vmui/src/constants/logs.ts +++ b/app/vmui/packages/vmui/src/constants/logs.ts @@ -1,2 +1,2 @@ export const LOGS_ENTRIES_LIMIT = 50; -export const LOGS_BARS_VIEW = 20; +export const LOGS_BARS_VIEW = 100; diff --git a/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogs.tsx b/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogs.tsx index c4a1c64a7c..a73a5bbff5 100644 --- a/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogs.tsx +++ b/app/vmui/packages/vmui/src/pages/ExploreLogs/GroupLogs/GroupLogs.tsx @@ -16,6 +16,7 @@ import TextField from "../../../components/Main/TextField/TextField"; import useBoolean from "../../../hooks/useBoolean"; import useStateSearchParams from "../../../hooks/useStateSearchParams"; import { useSearchParams } from "react-router-dom"; +import { getStreamPairs } from "../../../utils/logs"; const WITHOUT_GROUPING = "No Grouping"; @@ -62,12 +63,10 @@ const GroupLogs: FC = ({ logs, settingsRef }) => { const groupData = useMemo(() => { return groupByMultipleKeys(logs, [groupBy]).map((item) => { const streamValue = item.values[0]?.[groupBy] || ""; - const pairs = /^{.+}$/.test(streamValue) - ? streamValue.slice(1, -1).match(/(\\.|[^,])+/g) || [streamValue] - : [streamValue]; + const pairs = getStreamPairs(streamValue); return { ...item, - pairs: pairs.filter(Boolean), + pairs, }; }); }, [logs, groupBy]); diff --git a/app/vmui/packages/vmui/src/utils/logs.ts b/app/vmui/packages/vmui/src/utils/logs.ts new file mode 100644 index 0000000000..13e3d246c9 --- /dev/null +++ b/app/vmui/packages/vmui/src/utils/logs.ts @@ -0,0 +1,4 @@ +export const getStreamPairs = (value: string): string[] => { + const pairs = /^{.+}$/.test(value) ? value.slice(1, -1).split(",") : [value]; + return pairs.filter(Boolean); +}; diff --git a/docs/VictoriaLogs/CHANGELOG.md b/docs/VictoriaLogs/CHANGELOG.md index be2fec41a6..6feb45f2af 100644 --- a/docs/VictoriaLogs/CHANGELOG.md +++ b/docs/VictoriaLogs/CHANGELOG.md @@ -15,6 +15,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta ## tip +* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): improved readability of staircase graphs and tooltip usability. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6545#issuecomment-2336805237). +* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): simplify query input by adding only the label name when `ctrl`+clicking the line legend. See [this comment](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/6545#issuecomment-2336805237). * FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): keep selected columns in table view on page reloads. Before, selected columns were reset on each update. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7016). * FEATURE: allow skipping `_stream:` prefix in [stream filters](https://docs.victoriametrics.com/victorialogs/logsql/#stream-filter). This simplifies writing queries with stream filters. Now `{foo="bar"}` is the recommended format for stream filters over the `_stream:{foo="bar"}` format. * FEATURE: allow using `-` instead of `!` as `NOT` operator shorthand in [logical filters](https://docs.victoriametrics.com/victorialogs/logsql/#logical-filter). For example, `-info -warn` query is equivalent to `!info !warn`. This simplifies transition from other query languages with full-text search support, which usually use `-` as `NOT` operator.