app/vmui: small UX enhancements

- Reduce vertical space usage, so more information is available on the screen without the need to scroll.
- Show information for lines with higher values at the top of the legend under the graph.
  This should simplify graph analysis when it contains many lines.
This commit is contained in:
Aliaksandr Valialkin 2023-10-12 19:54:16 +02:00
parent ca35e0d66a
commit b86bec8109
No known key found for this signature in database
GPG key ID: A72BEC6CD3D0DED1
40 changed files with 4092 additions and 81 deletions

View file

@ -1,14 +1,13 @@
{ {
"files": { "files": {
"main.css": "./static/css/main.3258b6c4.css", "main.css": "./static/css/main.9a224445.css",
"main.js": "./static/js/main.41b816cc.js", "main.js": "./static/js/main.02178f4b.js",
"static/js/522.b5ae4365.chunk.js": "./static/js/522.b5ae4365.chunk.js", "static/js/522.b5ae4365.chunk.js": "./static/js/522.b5ae4365.chunk.js",
"static/media/Lato-Regular.ttf": "./static/media/Lato-Regular.d714fec1633b69a9c2e9.ttf", "static/media/MetricsQL.md": "./static/media/MetricsQL.957b90ab4cb4852eec26.md",
"static/media/Lato-Bold.ttf": "./static/media/Lato-Bold.32360ba4b57802daa4d6.ttf",
"index.html": "./index.html" "index.html": "./index.html"
}, },
"entrypoints": [ "entrypoints": [
"static/css/main.3258b6c4.css", "static/css/main.9a224445.css",
"static/js/main.41b816cc.js" "static/js/main.02178f4b.js"
] ]
} }

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.41b816cc.js"></script><link href="./static/css/main.3258b6c4.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html> <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.02178f4b.js"></script><link href="./static/css/main.9a224445.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1,14 +1,13 @@
{ {
"files": { "files": {
"main.css": "./static/css/main.4ab6595e.css", "main.css": "./static/css/main.d9ac05de.css",
"main.js": "./static/js/main.dbf8fb4f.js", "main.js": "./static/js/main.70434a4f.js",
"static/js/522.b5ae4365.chunk.js": "./static/js/522.b5ae4365.chunk.js", "static/js/522.b5ae4365.chunk.js": "./static/js/522.b5ae4365.chunk.js",
"static/media/Lato-Regular.ttf": "./static/media/Lato-Regular.d714fec1633b69a9c2e9.ttf", "static/media/MetricsQL.md": "./static/media/MetricsQL.957b90ab4cb4852eec26.md",
"static/media/Lato-Bold.ttf": "./static/media/Lato-Bold.32360ba4b57802daa4d6.ttf",
"index.html": "./index.html" "index.html": "./index.html"
}, },
"entrypoints": [ "entrypoints": [
"static/css/main.4ab6595e.css", "static/css/main.d9ac05de.css",
"static/js/main.dbf8fb4f.js" "static/js/main.70434a4f.js"
] ]
} }

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.dbf8fb4f.js"></script><link href="./static/css/main.4ab6595e.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html> <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=5"/><meta name="theme-color" content="#000000"/><meta name="description" content="UI for VictoriaMetrics"/><link rel="apple-touch-icon" href="./apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png"><link rel="manifest" href="./manifest.json"/><title>VM UI</title><script src="./dashboards/index.js" type="module"></script><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="./preview.jpg"><meta name="twitter:title" content="UI for VictoriaMetrics"><meta name="twitter:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta name="twitter:site" content="@VictoriaMetrics"><meta property="og:title" content="Metric explorer for VictoriaMetrics"><meta property="og:description" content="Explore and troubleshoot your VictoriaMetrics data"><meta property="og:image" content="./preview.jpg"><meta property="og:type" content="website"><script defer="defer" src="./static/js/main.70434a4f.js"></script><link href="./static/css/main.d9ac05de.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@ import classNames from "classnames";
import uPlot from "uplot"; import uPlot from "uplot";
import Button from "../../Main/Button/Button"; import Button from "../../Main/Button/Button";
import { CloseIcon, DragIcon } from "../../Main/Icons"; import { CloseIcon, DragIcon } from "../../Main/Icons";
import { SeriesItemStats } from "../../../types"; import { SeriesItemStatsFormatted } from "../../../types";
import { STATS_ORDER } from "../../../constants/graph"; import { STATS_ORDER } from "../../../constants/graph";
export interface ChartTooltipProps { export interface ChartTooltipProps {
@ -17,7 +17,7 @@ export interface ChartTooltipProps {
value: string | number | null; value: string | number | null;
point: { top: number, left: number }; point: { top: number, left: number };
unit?: string; unit?: string;
stats?: SeriesItemStats; statsFormatted?: SeriesItemStatsFormatted;
isSticky?: boolean; isSticky?: boolean;
info?: string; info?: string;
marker?: string; marker?: string;
@ -34,7 +34,7 @@ const ChartTooltip: FC<ChartTooltipProps> = ({
point, point,
unit = "", unit = "",
info, info,
stats, statsFormatted,
isSticky, isSticky,
marker, marker,
onClose onClose
@ -159,7 +159,7 @@ const ChartTooltip: FC<ChartTooltipProps> = ({
<b>{value}</b>{unit} <b>{value}</b>{unit}
</p> </p>
</div> </div>
{stats && ( {statsFormatted && (
<table className="vm-chart-tooltip-stats"> <table className="vm-chart-tooltip-stats">
{STATS_ORDER.map((key, i) => ( {STATS_ORDER.map((key, i) => (
<div <div
@ -167,7 +167,7 @@ const ChartTooltip: FC<ChartTooltipProps> = ({
key={i} key={i}
> >
<span className="vm-chart-tooltip-stats-row__key">{key}:</span> <span className="vm-chart-tooltip-stats-row__key">{key}:</span>
<span className="vm-chart-tooltip-stats-row__value">{stats[key]}</span> <span className="vm-chart-tooltip-stats-row__value">{statsFormatted[key]}</span>
</div> </div>
))} ))}
</table> </table>

View file

@ -35,7 +35,7 @@ const Legend: FC<LegendProps> = ({ labels, query, onChange }) => {
)} )}
> >
<div> <div>
{labels.filter(l => l.group === group).map((legendItem: LegendItemType) => {labels.filter(l => l.group === group).sort((x, y) => (y.median || 0) - (x.median || 0)).map((legendItem: LegendItemType) =>
<LegendItem <LegendItem
key={legendItem.label} key={legendItem.label}
legend={legendItem} legend={legendItem}

View file

@ -21,8 +21,8 @@ const LegendItem: FC<LegendItemProps> = ({ legend, onChange, isHeatmap }) => {
return isHeatmap ? result.filter(f => f.key !== "vmrange") : result; return isHeatmap ? result.filter(f => f.key !== "vmrange") : result;
}, [legend, isHeatmap]); }, [legend, isHeatmap]);
const calculations = legend.calculations; const statsFormatted = legend.statsFormatted;
const showCalculations = Object.values(calculations).some(v => v); const showStats = Object.values(statsFormatted).some(v => v);
const handleClickFreeField = async (val: string) => { const handleClickFreeField = async (val: string) => {
await copyToClipboard(val, `${val} has been copied`); await copyToClipboard(val, `${val} has been copied`);
@ -70,7 +70,7 @@ const LegendItem: FC<LegendItemProps> = ({ legend, onChange, isHeatmap }) => {
{!!freeFormFields.length && <>&#125;</>} {!!freeFormFields.length && <>&#125;</>}
</span> </span>
</div> </div>
{!isHeatmap && showCalculations && ( {!isHeatmap && showStats && (
<div className="vm-legend-item-stats"> <div className="vm-legend-item-stats">
{STATS_ORDER.map((key, i) => ( {STATS_ORDER.map((key, i) => (
<div <div
@ -78,7 +78,7 @@ const LegendItem: FC<LegendItemProps> = ({ legend, onChange, isHeatmap }) => {
key={i} key={i}
> >
<span className="vm-legend-item-stats-row__key">{key}:</span> <span className="vm-legend-item-stats-row__key">{key}:</span>
<span className="vm-legend-item-stats-row__value">{calculations[key]}</span> <span className="vm-legend-item-stats-row__value">{statsFormatted[key]}</span>
</div> </div>
))} ))}
</div> </div>

View file

@ -10,7 +10,6 @@
background-color: $color-background-block; background-color: $color-background-block;
cursor: pointer; cursor: pointer;
transition: 0.2s ease; transition: 0.2s ease;
margin-bottom: $padding-small;
font-size: $font-size-small; font-size: $font-size-small;
&:hover { &:hover {

View file

@ -7,6 +7,7 @@ $switch-handle-size: $switch-height - ($switch-padding * 2);
$switch-border-radius: $switch-handle-size + ($switch-padding * 2); $switch-border-radius: $switch-handle-size + ($switch-padding * 2);
.vm-switch { .vm-switch {
font-size: $font-size-small;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;

View file

@ -84,10 +84,10 @@
} }
&__input { &__input {
font-family: $font-family-monospace;
display: block; display: block;
border-radius: $border-radius-small; border-radius: $border-radius-small;
transition: border 200ms ease; transition: border 200ms ease;
min-height: 40px;
resize: none; resize: none;
overflow: hidden; overflow: hidden;
background-color: transparent; background-color: transparent;

View file

@ -89,12 +89,12 @@ const NestedNav: FC<RecursiveProps> = ({ isRoot, trace, totalMsec }) => {
})} })}
ref={messageRef} ref={messageRef}
> >
<span className="vm-nested-nav-header__message_duration">
{duration}
</span>:&nbsp;
<span>{trace.message}</span> <span>{trace.message}</span>
</div> </div>
<div className="vm-nested-nav-header-bottom"> <div className="vm-nested-nav-header-bottom">
<div className="vm-nested-nav-header-bottom__duration">
{`duration: ${duration}`}
</div>
{(isExpanded || showFullMessage) && ( {(isExpanded || showFullMessage) && (
<Button <Button
variant="text" variant="text"

View file

@ -5,7 +5,7 @@ $color-base-nested-nav-dark: $color-background-body;
.vm-nested-nav { .vm-nested-nav {
position: relative; position: relative;
margin-left: $padding-global; margin-left: $padding-small;
border-radius: $border-radius-small; border-radius: $border-radius-small;
&_dark &-header { &_dark &-header {
@ -58,7 +58,7 @@ $color-base-nested-nav-dark: $color-background-body;
content: ""; content: "";
position: absolute; position: absolute;
bottom: 50%; bottom: 50%;
left: calc($padding-global / -2); left: calc(-1 * $padding-small);
height: calc(50% + $padding-small); height: calc(50% + $padding-small);
width: 2px; width: 2px;
background-color: $color-base-nested-nav; background-color: $color-base-nested-nav;
@ -103,6 +103,10 @@ $color-base-nested-nav-dark: $color-background-body;
display: block; display: block;
overflow: visible; overflow: visible;
} }
&_duration {
color: $color-text-secondary;
}
} }
&-bottom { &-bottom {
@ -110,10 +114,6 @@ $color-base-nested-nav-dark: $color-background-body;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
align-items: center; align-items: center;
grid-column: 2; grid-column: 2;
&__duration {
color: $color-text-secondary;
}
} }
} }
@ -122,7 +122,7 @@ $color-base-nested-nav-dark: $color-background-body;
content: ""; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
left: calc($padding-global / -2); left: calc(-1 * $padding-small);
height: 100%; height: 100%;
width: 2px; width: 2px;
background-color: $color-base-nested-nav; background-color: $color-base-nested-nav;

View file

@ -1,4 +1,4 @@
import { GraphSize, SeriesItemStats } from "../types"; import { GraphSize, SeriesItemStatsFormatted } from "../types";
export const MAX_QUERY_FIELDS = 4; export const MAX_QUERY_FIELDS = 4;
export const MAX_QUERIES_HISTORY = 25; export const MAX_QUERIES_HISTORY = 25;
@ -11,11 +11,11 @@ export const DEFAULT_MAX_SERIES = {
export const GRAPH_SIZES: GraphSize[] = [ export const GRAPH_SIZES: GraphSize[] = [
{ {
id: "small", id: "small",
isDefault: true,
height: () => window.innerHeight * 0.2 height: () => window.innerHeight * 0.2
}, },
{ {
id: "medium", id: "medium",
isDefault: true,
height: () => window.innerHeight * 0.4 height: () => window.innerHeight * 0.4
}, },
{ {
@ -24,4 +24,4 @@ export const GRAPH_SIZES: GraphSize[] = [
}, },
]; ];
export const STATS_ORDER: (keyof SeriesItemStats)[] = ["min", "median", "max"]; export const STATS_ORDER: (keyof SeriesItemStatsFormatted)[] = ["min", "median", "max"];

View file

@ -64,7 +64,7 @@ const useLineTooltip = ({ u, metrics, series, unit }: LineTooltipHook) => {
dates: [date ? dayjs(date * 1000).tz().format(DATE_FULL_TIMEZONE_FORMAT) : "-"], dates: [date ? dayjs(date * 1000).tz().format(DATE_FULL_TIMEZONE_FORMAT) : "-"],
value: formatPrettyNumber(value, min, max), value: formatPrettyNumber(value, min, max),
info: getMetricName(metricItem), info: getMetricName(metricItem),
stats: seriesItem?.calculations, statsFormatted: seriesItem?.statsFormatted,
marker: `${seriesItem?.stroke}`, marker: `${seriesItem?.stroke}`,
}; };
}, [u, tooltipIdx, metrics, series, unit]); }, [u, tooltipIdx, metrics, series, unit]);

View file

@ -24,6 +24,7 @@
&__button { &__button {
display: grid; display: grid;
align-items: start;
width: 36px; width: 36px;
min-height: 36px; min-height: 36px;
} }

View file

@ -26,9 +26,8 @@
} }
&-cell { &-cell {
padding: 12px; padding: 4px;
border-bottom: $border-divider; border-bottom: $border-divider;
height: 40px;
vertical-align: top; vertical-align: top;
line-height: 1.5; line-height: 1.5;
overflow-wrap: anywhere; overflow-wrap: anywhere;

View file

@ -1,15 +0,0 @@
@font-face {
font-family: 'Lato';
src: url('../assets/fonts/Lato/Lato-Regular.ttf');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lato';
src: url('../assets/fonts/Lato/Lato-Bold.ttf');
font-weight: bold;
font-style: normal;
font-display: swap;
}

View file

@ -1,7 +1,6 @@
@forward "variables"; @forward "variables";
@forward "core"; @forward "core";
@forward "reset"; @forward "reset";
@forward "fonts";
@forward "./components/header-button"; @forward "./components/header-button";
@forward "./components/list"; @forward "./components/list";

View file

@ -31,14 +31,14 @@ $color-background-tooltip: var(--color-background-tooltip);
/************* padding *************/ /************* padding *************/
$padding-global: 16px; $padding-global: 12px;
$padding-large: 48px; $padding-large: 16px;
$padding-medium: 24px; $padding-medium: 12px;
$padding-small: 8px; $padding-small: 8px;
/************* fonts *************/ /************* fonts *************/
$font-family-global: 'Lato', sans-serif; $font-family-global: system-ui;
$font-family-monospace: monospace; $font-family-monospace: monospace;
$font-size-large: 18px; $font-size-large: 18px;
$font-size-medium: 16px; $font-size-medium: 16px;

View file

@ -1,6 +1,6 @@
import { Axis, Series } from "uplot"; import { Axis, Series } from "uplot";
export interface SeriesItemStats { export interface SeriesItemStatsFormatted {
min: string, min: string,
max: string, max: string,
median: string, median: string,
@ -9,7 +9,8 @@ export interface SeriesItemStats {
export interface SeriesItem extends Series { export interface SeriesItem extends Series {
freeFormFields: {[key: string]: string}; freeFormFields: {[key: string]: string};
calculations: SeriesItemStats statsFormatted: SeriesItemStatsFormatted;
median: number
} }
export interface HideSeriesArgs { export interface HideSeriesArgs {
@ -29,12 +30,8 @@ export interface LegendItemType {
color: string; color: string;
checked: boolean; checked: boolean;
freeFormFields: {[key: string]: string}; freeFormFields: {[key: string]: string};
calculations: { statsFormatted: SeriesItemStatsFormatted;
min: string; median: number
max: string;
median: string;
last: string;
}
} }
export interface BarSeriesItem { export interface BarSeriesItem {

View file

@ -8,7 +8,7 @@ import { formatPrettyNumber } from "./helpers";
export const getSeriesItemContext = (data: MetricResult[], hideSeries: string[], alias: string[]) => { export const getSeriesItemContext = (data: MetricResult[], hideSeries: string[], alias: string[]) => {
const colorState: {[key: string]: string} = {}; const colorState: {[key: string]: string} = {};
const calculations = data.map(d => { const stats = data.map(d => {
const values = d.values.map(v => promValueToNumber(v[1])); const values = d.values.map(v => promValueToNumber(v[1]));
return { return {
min: getMinFromArray(values), min: getMinFromArray(values),
@ -27,7 +27,7 @@ export const getSeriesItemContext = (data: MetricResult[], hideSeries: string[],
return (d: MetricResult, i: number): SeriesItem => { return (d: MetricResult, i: number): SeriesItem => {
const label = getNameForMetric(d, alias[d.group - 1]); const label = getNameForMetric(d, alias[d.group - 1]);
const color = colorState[label] || getColorFromString(label); const color = colorState[label] || getColorFromString(label);
const { min, max, median, last } = calculations[i]; const { min, max, median, last } = stats[i];
return { return {
label, label,
@ -40,12 +40,13 @@ export const getSeriesItemContext = (data: MetricResult[], hideSeries: string[],
size: 4.2, size: 4.2,
width: 1.4 width: 1.4
}, },
calculations: { statsFormatted: {
min: formatPrettyNumber(min, min, max), min: formatPrettyNumber(min, min, max),
max: formatPrettyNumber(max, min, max), max: formatPrettyNumber(max, min, max),
median: formatPrettyNumber(median, min, max), median: formatPrettyNumber(median, min, max),
last: formatPrettyNumber(last, min, max), last: formatPrettyNumber(last, min, max),
} },
median: median,
}; };
}; };
}; };
@ -56,7 +57,8 @@ export const getLegendItem = (s: SeriesItem, group: number): LegendItemType => (
color: s.stroke as string, color: s.stroke as string,
checked: s.show || false, checked: s.show || false,
freeFormFields: s.freeFormFields, freeFormFields: s.freeFormFields,
calculations: s.calculations, statsFormatted: s.statsFormatted,
median: s.median,
}); });
export const getHideSeries = ({ hideSeries, legend, metaKey, series }: HideSeriesArgs): string[] => { export const getHideSeries = ({ hideSeries, legend, metaKey, series }: HideSeriesArgs): string[] => {

View file

@ -42,6 +42,8 @@ The sandbox cluster installation is running under the constant load generated by
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add support for functions, labels, values in autocomplete. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3006). * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add support for functions, labels, values in autocomplete. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/3006).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): retain specified time interval when executing a query from `Top Queries`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5097). * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): retain specified time interval when executing a query from `Top Queries`. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5097).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): improve repeated VMUI page load times by enabling caching of static js and css at web browser side according to [these recommendations](https://developer.chrome.com/docs/lighthouse/performance/uses-long-cache-ttl/). * FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): improve repeated VMUI page load times by enabling caching of static js and css at web browser side according to [these recommendations](https://developer.chrome.com/docs/lighthouse/performance/uses-long-cache-ttl/).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): show information about lines with bigger values at the top of the legend under the graph in order to simplify graph analysis.
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): reduce vertical space usage, so more information is visible on the screen without scrolling.
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert.html): strip sensitive information such as auth headers or passwords from datasource, remote-read, remote-write or notifier URLs in log messages or UI. This behavior is by default and is controlled via `-datasource.showURL`, `-remoteRead.showURL`, `remoteWrite.showURL` or `-notifier.showURL` cmd-line flags. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5044). * BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert.html): strip sensitive information such as auth headers or passwords from datasource, remote-read, remote-write or notifier URLs in log messages or UI. This behavior is by default and is controlled via `-datasource.showURL`, `-remoteRead.showURL`, `remoteWrite.showURL` or `-notifier.showURL` cmd-line flags. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5044).
* BUGFIX: [vmselect](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): improve performance and memory usage during query processing on machines with big number of CPU cores. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5087) for details. * BUGFIX: [vmselect](https://docs.victoriametrics.com/Cluster-VictoriaMetrics.html): improve performance and memory usage during query processing on machines with big number of CPU cores. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5087) for details.