vmui: fix predefined panels

### Describe Your Changes

- Fixes the handling of the `showLegend` flag.  
- Fixes the handling of `alias`.  
- Adds support for alias templates, allowing dynamic substitutions like
`{{label_name}}`.

Related issue:
https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7565
This commit is contained in:
Yury Molodov 2024-11-28 13:47:37 +01:00 committed by GitHub
parent 0f06d2f072
commit dec9a2f023
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 84 additions and 35 deletions

View file

@ -37,7 +37,7 @@ type panelSettings struct {
Unit string `json:"unit,omitempty"`
Expr []string `json:"expr"`
Alias []string `json:"alias,omitempty"`
ShowLegend bool `json:"showLegend,omitempty"`
ShowLegend *bool `json:"showLegend"`
Width int `json:"width,omitempty"`
}
@ -107,6 +107,17 @@ func collectDashboardsSettings(path string) ([]byte, error) {
if err != nil {
return nil, fmt.Errorf("cannot parse file %s: %w", filePath, err)
}
for i := range ds.Rows {
for j := range ds.Rows[i].Panels {
// Set default value for ShowLegend = true if it is not specified
if ds.Rows[i].Panels[j].ShowLegend == nil {
defaultValue := true
ds.Rows[i].Panels[j].ShowLegend = &defaultValue
}
}
}
if len(ds.Rows) > 0 {
dss = append(dss, ds)
}

View file

@ -127,15 +127,27 @@ DashboardRow:
<br/>
PanelSettings:
| Name | Type | Description |
|:------------|:----------:|--------------------------------------------------------------------------------------:|
| expr* | `string[]` | Data source queries |
| alias | `string[]` | Expression alias. Matched by index in array |
| title | `string` | Panel title |
| description | `string` | Additional information about the panel |
| unit | `string` | Y-axis unit |
| showLegend | `boolean` | If `false`, the legend hide. Default value - `true` |
| width | `number` | The number of columns the panel uses.<br/> From 1 (minimum width) to 12 (full width). |
| Name | Type | Description |
|:------------|:----------:|---------------------------------------------------------------------------------------------------------------:|
| expr* | `string[]` | Data source queries |
| alias | `string[]` | An array of aliases for each expression in `expr`. See [Template Support in alias](#template-support-in-alias) |
| title | `string` | Panel title |
| description | `string` | Additional information about the panel |
| unit | `string` | Y-axis unit |
| showLegend | `boolean` | If `false`, the legend hide. Default value - `true` |
| width | `number` | The number of columns the panel uses.<br/> From 1 (minimum width) to 12 (full width). |
### Template Support in `alias`
To create more readable metric names in the legend, you can use constructions like `{{label_name}}`, where `label_name`
is the label's name.
If the label exists in the metric, its value will be substituted in the template.
If the label is missing, the legend will use the default name.
**Example:**
Metric: `metric{foo="bar",baz="qux"}`
Alias: `{{foo}} - {{baz}}`
Legend: `bar - qux`
### Example json

View file

@ -56,19 +56,23 @@ const LegendItem: FC<LegendItemProps> = ({ legend, onChange, isHeatmap, isAnomal
)}
<div className="vm-legend-item-info">
<span className="vm-legend-item-info__label">
{legend.freeFormFields["__name__"]}
{!!freeFormFields.length && <>&#123;</>}
{freeFormFields.map((f, i) => (
<span
className="vm-legend-item-info__free-fields"
key={f.key}
onClick={createHandlerCopy(f.freeField)}
title="copy to clipboard"
>
{f.freeField}{i + 1 < freeFormFields.length && ","}
</span>
))}
{!!freeFormFields.length && <>&#125;</>}
{legend.hasAlias ? legend.label : (
<>
{legend.freeFormFields["__name__"]}
{!!freeFormFields.length && <>&#123;</>}
{freeFormFields.map((f, i) => (
<span
className="vm-legend-item-info__free-fields"
key={f.key}
onClick={createHandlerCopy(f.freeField)}
title="copy to clipboard"
>
{f.freeField}{i + 1 < freeFormFields.length && ","}
</span>
))}
{!!freeFormFields.length && <>&#125;</>}
</>
)}
</span>
</div>
{!isHeatmap && showStats && (

View file

@ -64,7 +64,7 @@ const useLineTooltip = ({ u, metrics, series, unit, isAnomalyView }: LineTooltip
title: groups.size > 1 && !isAnomalyView ? `Query ${group}` : "",
dates: [date ? dayjs(date * 1000).tz().format(DATE_FULL_TIMEZONE_FORMAT) : "-"],
value: formatPrettyNumber(value, min, max),
info: getMetricName(metricItem),
info: getMetricName(metricItem, seriesItem),
statsFormatted: seriesItem?.statsFormatted,
marker: `${seriesItem?.stroke}`,
};

View file

@ -23,6 +23,7 @@ export interface SeriesItem extends Series {
median: number;
forecast?: ForecastType | null;
forecastGroup?: string;
hasAlias?: boolean;
}
export interface HideSeriesArgs {
@ -45,6 +46,7 @@ export interface LegendItemType {
freeFormFields: {[key: string]: string};
statsFormatted: SeriesItemStatsFormatted;
median: number
hasAlias: boolean;
}
export interface BarSeriesItem {

View file

@ -2,16 +2,23 @@ import { MetricBase } from "../api/types";
export const getNameForMetric = (result: MetricBase, alias?: string, showQueryNum = true): string => {
const { __name__, ...freeFormFields } = result.metric;
const name = alias || `${showQueryNum ? `[Query ${result.group}] ` : ""}${__name__ || ""}`;
if (Object.keys(freeFormFields).length == 0) {
if (!name) {
return "value";
}
return name;
const queryPrefix = showQueryNum ? `[Query ${result.group}] ` : "";
if (alias) {
return alias.replace(/\{\{(\w+)}}/g, (_, key) => result.metric[key] || "");
}
return `${name}{${Object.entries(freeFormFields).map(e =>
`${e[0]}=${JSON.stringify(e[1])}`
).join(", ")}}`;
const name = `${queryPrefix}${__name__ || ""}`;
if (Object.keys(freeFormFields).length === 0) {
return name || "value";
}
const fieldsString = Object.entries(freeFormFields)
.map(([key, value]) => `${key}=${JSON.stringify(value)}`)
.join(", ");
return `${name}{${fieldsString}}`;
};
export const promValueToNumber = (s: string): number => {

View file

@ -1,5 +1,6 @@
import uPlot from "uplot";
import { MetricResult } from "../../api/types";
import { SeriesItem } from "../../types";
export const formatTicks = (u: uPlot, ticks: number[], unit = ""): string[] => {
const min = ticks[0];
@ -53,7 +54,11 @@ export const getDashLine = (group: number): number[] => {
return group <= 1 ? [] : [group*4, group*1.2];
};
export const getMetricName = (metricItem: MetricResult) => {
export const getMetricName = (metricItem: MetricResult, seriesItem: SeriesItem) => {
if (seriesItem?.hasAlias && seriesItem?.label) {
return seriesItem.label;
}
const metric = metricItem?.metric || {};
const labelNames = Object.keys(metric).filter(x => x != "__name__");
const labels = labelNames.map(key => `${key}=${JSON.stringify(metric[key])}`);

View file

@ -42,10 +42,12 @@ export const getSeriesItemContext = (data: MetricResult[], hideSeries: string[],
return (d: MetricResult, i: number): SeriesItem => {
const metricInfo = isAnomalyUI ? isForecast(data[i].metric) : null;
const label = isAnomalyUI ? metricInfo?.group || "" : getNameForMetric(d, alias[d.group - 1]);
const aliasValue = alias[d.group - 1];
const label = isAnomalyUI ? metricInfo?.group || "" : getNameForMetric(d, aliasValue);
return {
label,
hasAlias: Boolean(aliasValue),
dash: getDashSeries(metricInfo),
width: getWidthSeries(metricInfo),
stroke: getStrokeSeries({ metricInfo, label, isAnomalyUI, colorState }),
@ -88,6 +90,7 @@ export const getLegendItem = (s: SeriesItem, group: number): LegendItemType => (
freeFormFields: s.freeFormFields,
statsFormatted: s.statsFormatted,
median: s.median,
hasAlias: s.hasAlias || false,
});
export const getHideSeries = ({ hideSeries, legend, metaKey, series, isAnomalyView }: HideSeriesArgs): string[] => {

View file

@ -18,6 +18,9 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): add frontend-only pagination for table view.
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): improve memory consumption during data processing. This enhancement reduces the overall memory footprint, leading to better performance and stability.
* FEATURE: [web UI](https://docs.victoriametrics.com/victorialogs/querying/#web-ui): reduce memory usage across all tabs for improved performance and stability. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7185).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add support for template alias in predefined panels. This allows creating more readable metric names in the legend using constructions like `{{label_name}}`, where `label_name` is the name of the label. [See this commit](https://github.com/VictoriaMetrics/VictoriaMetrics/commit/116101da78a4dee8bd7c4ba0e66458fd05a10469#diff-95141489b32468cf852d2705d96eaa48c50a8b1cdd0424a29e7ca289912a6dcbR140-R151)
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix for `showLegend` and `alias` flags in predefined panels. [See this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7565)
## [v1.0.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.0.0-victorialogs)

View file

@ -22,6 +22,7 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
* FEATURE: [vmalert](https://docs.victoriametrics.com/vmalert): revert the default value of `-remoteWrite.maxQueueSize` from `1_000_000` to `100_000`. It was bumped in [v1.104.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.104.0), which increases memory usage and is not needed for most setups. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7471).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add `Raw Query` tab for displaying raw data. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7024).
* FEATURE: [vmui](https://docs.victoriametrics.com/#vmui): add support for template alias in predefined panels. This allows creating more readable metric names in the legend using constructions like `{{label_name}}`, where `label_name` is the name of the label. [See this commit](https://github.com/VictoriaMetrics/VictoriaMetrics/commit/116101da78a4dee8bd7c4ba0e66458fd05a10469#diff-95141489b32468cf852d2705d96eaa48c50a8b1cdd0424a29e7ca289912a6dcbR140-R151)
* FEATURE: [stream aggregation](https://docs.victoriametrics.com/stream-aggregation/): add `ignore_first_sample_interval` param to [aggregation config](https://docs.victoriametrics.com/stream-aggregation/#stream-aggregation-config). It allows users to control the time interval when aggregation skips sending aggregated samples to avoid unexpected spikes in values. By default, this interval is set to x2 of `staleness_interval`. The new setting is applicable only to `total`, `total_prometheus`, `increase`, `increase_prometheus` and `histogram_bucket` outputs. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7116) for details. Thanks to @iyuroch for the [pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/7313).
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): add `dump_request_on_errors` bool setting to [auth config](https://docs.victoriametrics.com/vmauth/#auth-config) for debugging HTTP requests that missed routing rules. This should improve debugability of vmauth settings.
* FEATURE: [vmauth](https://docs.victoriametrics.com/vmauth/): add `dryRun` flag to validate configuration. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7505) for details.
@ -32,6 +33,7 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
* BUGFIX: [vmagent](https://docs.victoriametrics.com/vmagent): fix the `resource_group` filter for Azure service discovery on virtual machine scale sets. Previously, this filter did not apply to virtual machine scale sets, causing all virtual machines to be discovered. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7630).
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/), `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): properly return result for binary operation `^` aka pow at query requests for `NaN` values. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7359) for details.
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix rendering of isolated data points on the graph that are not connected to other points.
* BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix for `showLegend` and `alias` flags in predefined panels. [See this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7565)
* BUGFIX: [vmalert](https://docs.victoriametrics.com/vmalert): improve the correctness of alert [state restoration](https://docs.victoriametrics.com/vmalert/#alerts-state-on-restarts). Previously, it could result in false-positive alerts if alert was resolved shortly before vmalert restart.
* BUGFIX: [vmalert-tool](https://docs.victoriametrics.com/vmalert-tool/): exit immediately with error message if no test file is found under specified `-files`.
* BUGFIX: `vmselect` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/): Properly handle [multitenant](https://docs.victoriametrics.com/cluster-victoriametrics/#multitenancy-via-labels) query request errors and correctly perform search for available tenants. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/7549) for details. This is follow-up after [v1.106.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.106.1) release changes.