mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 05:29:45 +00:00
Guide stored charts on Overview without losing incident peaks
Replace the removed PBS drawer History route with the current Overview chart and range control, while preserving older installed tabs and safe no-replay diagnosis. Explain bucket averages, low-high bounds and local peaks without treating them as continuous coverage or incident timestamps. Keep both shipped guide mirrors and their rendered links checked. Contract-Neutral: Existing documentation and consuming guide tests only; no monitoring, storage, permissions, entitlement or navigation contract changes. Change-source: pulse-maintainer
This commit is contained in:
@@ -4,6 +4,19 @@ Pulse persists metrics history to disk so trend views and sparklines survive res
|
||||
|
||||
## Read a History panel
|
||||
|
||||
In current drawers, open the affected resource's **Overview** and use **History
|
||||
range** beside its charts. Proxmox guests and nodes, Docker hosts and resource
|
||||
drawers (including PBS) show stored charts there instead of a separate History
|
||||
tab. If your installed version still has a **History** tab, use that tab; do not
|
||||
upgrade or restart just to follow this guide. A resource without a supported
|
||||
history target may have no chart.
|
||||
|
||||
These charts are separate from **Alerts → History**, table sparklines and
|
||||
current summary cards. A current card or a short trend preview does not
|
||||
establish the observations in the selected stored range. For a PBS host, use
|
||||
the [Backup Server chart](PBS.md#pbs-is-connected-but-history-stays-empty),
|
||||
not its datastore or the VM that happens to host it.
|
||||
|
||||
Start with the existing chart, not a restart or a storage change. A current
|
||||
reading does not prove that it was stored, and a selected time range does not
|
||||
prove continuous coverage. **Window start** and **Window end** bound the
|
||||
@@ -20,12 +33,21 @@ than borrowing one from the current overview.
|
||||
| **current**, **last known** or **freshness unknown** with no stored history | A separately qualified fallback reading. Keep its label and explanation. | Not proof that the value was persisted or belongs to a past incident. |
|
||||
| **Single observation. No trend yet.** | One stored time in that panel. | Not a flat trend or sustained recovery. |
|
||||
| **Missing observations** | Some series lack readings at other stored times in that panel; lines stop across those gaps. | Not the cause or duration of a monitoring outage. Missing is not measured zero. |
|
||||
| **Shaded low–high band** | The recorded minimum and maximum within an aggregated bucket, when supplied; the line shows its average. | Not continuous coverage, every original sample, or the duration of a spike. |
|
||||
| **peak** while inspecting | That metric's maximum in the inspected bucket, when the panel shows it beside the average. | Not necessarily the highest value in the whole selected range or the value at an alert's exact time. |
|
||||
|
||||
For example, CPU **22% at 12:02** and memory **95% at 12:01** are not one
|
||||
observation. At **Latest stored · 12:02**, memory is a dash if there is no
|
||||
memory point at 12:02; the earlier 95% remains inspectable. Network and disk
|
||||
I/O panels have their own times, not a shared snapshot of the guest.
|
||||
|
||||
An aggregated CPU bucket can show **22% average, 10% to 95%**. The line at 22%
|
||||
does not rule out the recorded 95% peak, and the band does not say how long
|
||||
that peak lasted. No visible band may mean a single reading, equal bounds or
|
||||
unavailable bounds; it does not prove that usage stayed constant. Older panels
|
||||
may not show these bounds. Keep that limitation rather than inferring a peak
|
||||
from the line alone.
|
||||
|
||||
1. Keep the same resource, metric and range when comparing existing readings.
|
||||
**Inspect history**, when offered, steps through stored times: focus the
|
||||
slider and use the arrow keys, **Home** or **End**, or move it by touch.
|
||||
|
||||
+15
-7
@@ -429,12 +429,19 @@ the pause. Monitoring and alerts are unavailable while Pulse is stopped.
|
||||
|
||||
### PBS is connected but History stays empty
|
||||
|
||||
Open **Proxmox → Backups → Backup Server → History**, not a datastore or the
|
||||
PBS virtual machine's row in **Overview**. Record which route fails. A working
|
||||
VM chart can use a different metrics target from the PBS host chart; it does
|
||||
not establish that the PBS chart can read the same series. Current CPU and
|
||||
memory values, a green connection badge, and an **API+Agent** label also do not
|
||||
prove that stored host history is available.
|
||||
Open **Proxmox → Backups**, choose the **Backup Server** row, then use the
|
||||
drawer's **Overview** charts and **History range** selector. If your installed
|
||||
version still has a separate **History** tab, use that tab instead; no upgrade
|
||||
or restart is needed just to find the chart. This is not a datastore chart,
|
||||
**Alerts → History**, or the PBS virtual machine's row in Proxmox **Overview**.
|
||||
Record which route fails. A working VM chart can use a different metrics target
|
||||
from the PBS host chart; it does not establish that the PBS chart can read the
|
||||
same series. Current CPU and memory values, a green connection badge, and an
|
||||
**API+Agent** label also do not prove that stored host history is available.
|
||||
|
||||
Use the chart's selected stored range, not a current summary card or table
|
||||
sparkline. For observation times, missing samples and aggregated low–high bands,
|
||||
see [reading a History panel](METRICS_HISTORY.md#read-a-history-panel).
|
||||
|
||||
Start with one affected PBS and a recent, unlocked time range:
|
||||
|
||||
@@ -447,7 +454,8 @@ Start with one affected PBS and a recent, unlocked time range:
|
||||
2. If the target is already known, inspect the chart's request instead of
|
||||
collecting the identities again. In your signed-in browser, open developer
|
||||
tools → **Network**, filter for `metrics-store/history`, then open the
|
||||
affected **History** tab. Do not refresh or restart the server. Inspect one
|
||||
affected drawer's **Overview** charts (or **History** tab on older versions).
|
||||
Do not refresh or restart the server. Inspect one
|
||||
completed request for the drawer's `resourceType`, `resourceId` and `range`.
|
||||
The drawer normally fetches all chart metrics together: a request **without
|
||||
`metric`** is expected, so do not wait for a separate `metric=cpu` request.
|
||||
|
||||
@@ -4,6 +4,19 @@ Pulse persists metrics history to disk so trend views and sparklines survive res
|
||||
|
||||
## Read a History panel
|
||||
|
||||
In current drawers, open the affected resource's **Overview** and use **History
|
||||
range** beside its charts. Proxmox guests and nodes, Docker hosts and resource
|
||||
drawers (including PBS) show stored charts there instead of a separate History
|
||||
tab. If your installed version still has a **History** tab, use that tab; do not
|
||||
upgrade or restart just to follow this guide. A resource without a supported
|
||||
history target may have no chart.
|
||||
|
||||
These charts are separate from **Alerts → History**, table sparklines and
|
||||
current summary cards. A current card or a short trend preview does not
|
||||
establish the observations in the selected stored range. For a PBS host, use
|
||||
the [Backup Server chart](PBS.md#pbs-is-connected-but-history-stays-empty),
|
||||
not its datastore or the VM that happens to host it.
|
||||
|
||||
Start with the existing chart, not a restart or a storage change. A current
|
||||
reading does not prove that it was stored, and a selected time range does not
|
||||
prove continuous coverage. **Window start** and **Window end** bound the
|
||||
@@ -20,12 +33,21 @@ than borrowing one from the current overview.
|
||||
| **current**, **last known** or **freshness unknown** with no stored history | A separately qualified fallback reading. Keep its label and explanation. | Not proof that the value was persisted or belongs to a past incident. |
|
||||
| **Single observation. No trend yet.** | One stored time in that panel. | Not a flat trend or sustained recovery. |
|
||||
| **Missing observations** | Some series lack readings at other stored times in that panel; lines stop across those gaps. | Not the cause or duration of a monitoring outage. Missing is not measured zero. |
|
||||
| **Shaded low–high band** | The recorded minimum and maximum within an aggregated bucket, when supplied; the line shows its average. | Not continuous coverage, every original sample, or the duration of a spike. |
|
||||
| **peak** while inspecting | That metric's maximum in the inspected bucket, when the panel shows it beside the average. | Not necessarily the highest value in the whole selected range or the value at an alert's exact time. |
|
||||
|
||||
For example, CPU **22% at 12:02** and memory **95% at 12:01** are not one
|
||||
observation. At **Latest stored · 12:02**, memory is a dash if there is no
|
||||
memory point at 12:02; the earlier 95% remains inspectable. Network and disk
|
||||
I/O panels have their own times, not a shared snapshot of the guest.
|
||||
|
||||
An aggregated CPU bucket can show **22% average, 10% to 95%**. The line at 22%
|
||||
does not rule out the recorded 95% peak, and the band does not say how long
|
||||
that peak lasted. No visible band may mean a single reading, equal bounds or
|
||||
unavailable bounds; it does not prove that usage stayed constant. Older panels
|
||||
may not show these bounds. Keep that limitation rather than inferring a peak
|
||||
from the line alone.
|
||||
|
||||
1. Keep the same resource, metric and range when comparing existing readings.
|
||||
**Inspect history**, when offered, steps through stored times: focus the
|
||||
slider and use the arrow keys, **Home** or **End**, or move it by touch.
|
||||
|
||||
@@ -429,12 +429,19 @@ the pause. Monitoring and alerts are unavailable while Pulse is stopped.
|
||||
|
||||
### PBS is connected but History stays empty
|
||||
|
||||
Open **Proxmox → Backups → Backup Server → History**, not a datastore or the
|
||||
PBS virtual machine's row in **Overview**. Record which route fails. A working
|
||||
VM chart can use a different metrics target from the PBS host chart; it does
|
||||
not establish that the PBS chart can read the same series. Current CPU and
|
||||
memory values, a green connection badge, and an **API+Agent** label also do not
|
||||
prove that stored host history is available.
|
||||
Open **Proxmox → Backups**, choose the **Backup Server** row, then use the
|
||||
drawer's **Overview** charts and **History range** selector. If your installed
|
||||
version still has a separate **History** tab, use that tab instead; no upgrade
|
||||
or restart is needed just to find the chart. This is not a datastore chart,
|
||||
**Alerts → History**, or the PBS virtual machine's row in Proxmox **Overview**.
|
||||
Record which route fails. A working VM chart can use a different metrics target
|
||||
from the PBS host chart; it does not establish that the PBS chart can read the
|
||||
same series. Current CPU and memory values, a green connection badge, and an
|
||||
**API+Agent** label also do not prove that stored host history is available.
|
||||
|
||||
Use the chart's selected stored range, not a current summary card or table
|
||||
sparkline. For observation times, missing samples and aggregated low–high bands,
|
||||
see [reading a History panel](METRICS_HISTORY.md#read-a-history-panel).
|
||||
|
||||
Start with one affected PBS and a recent, unlocked time range:
|
||||
|
||||
@@ -447,7 +454,8 @@ Start with one affected PBS and a recent, unlocked time range:
|
||||
2. If the target is already known, inspect the chart's request instead of
|
||||
collecting the identities again. In your signed-in browser, open developer
|
||||
tools → **Network**, filter for `metrics-store/history`, then open the
|
||||
affected **History** tab. Do not refresh or restart the server. Inspect one
|
||||
affected drawer's **Overview** charts (or **History** tab on older versions).
|
||||
Do not refresh or restart the server. Inspect one
|
||||
completed request for the drawer's `resourceType`, `resourceId` and `range`.
|
||||
The drawer normally fetches all chart metrics together: a request **without
|
||||
`metric`** is expected, so do not wait for a separate `metric=cpu` request.
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { createGuideFixture } from './guideFixture';
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../..');
|
||||
const read = (file: string) => readFileSync(path.join(root, file), 'utf8');
|
||||
const shipped = (name: string) => read(`frontend-modern/public/docs/${name}.md`);
|
||||
const render = createGuideFixture(shipped);
|
||||
const prose = (element: Element) => (element.textContent ?? '').replace(/\s+/g, ' ').trim();
|
||||
|
||||
function section(name: string, fragment: string) {
|
||||
const heading = render(name).querySelector(`#${fragment}`);
|
||||
expect(heading).not.toBeNull();
|
||||
const element = document.createElement('section');
|
||||
for (let next = heading!.nextElementSibling; next; next = next.nextElementSibling) {
|
||||
if (next.matches('h1, h2, h3')) break;
|
||||
element.appendChild(next.cloneNode(true));
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
const pbs = () => section('PBS', 'pbs-is-connected-but-history-stays-empty');
|
||||
const history = () => section('METRICS_HISTORY', 'read-a-history-panel');
|
||||
|
||||
describe('stored-chart navigation and interpretation help', () => {
|
||||
it.each(['PBS', 'METRICS_HISTORY'])('ships the exact canonical %s guide', (name) => {
|
||||
expect(shipped(name)).toBe(read(`docs/${name}.md`));
|
||||
});
|
||||
|
||||
it('routes PBS to its host Overview, not its datastore, VM or alert history', () => {
|
||||
const text = prose(pbs());
|
||||
expect(text).toContain('Proxmox → Backups, choose the Backup Server row');
|
||||
expect(text).toContain("drawer's Overview charts and History range selector");
|
||||
expect(text).toContain('not a datastore chart, Alerts → History');
|
||||
expect(text).toContain("PBS virtual machine's row in Proxmox Overview");
|
||||
expect(text).not.toContain('Backup Server → History');
|
||||
expect(text).toContain('resourceType, resourceId and range');
|
||||
expect(text).toContain('a request without metric is expected');
|
||||
expect(text).toContain('metrics.cpu');
|
||||
expect(text).toContain('points array for that single metric');
|
||||
});
|
||||
|
||||
it('supports older installed tabs without making an upgrade part of diagnosis', () => {
|
||||
expect(prose(pbs())).toContain('If your installed version still has a separate History tab');
|
||||
expect(prose(pbs())).toContain('no upgrade or restart is needed just to find the chart');
|
||||
expect(prose(history())).toContain('If your installed version still has a History tab');
|
||||
expect(prose(history())).toContain('do not upgrade or restart just to follow this guide');
|
||||
expect(prose(history())).toContain(
|
||||
'A resource without a supported history target may have no chart',
|
||||
);
|
||||
});
|
||||
|
||||
it('binds the new instructions to the current consuming drawer and control', () => {
|
||||
const overview = read(
|
||||
'frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx',
|
||||
);
|
||||
expect(overview).toContain('<GuestDrawerHistory');
|
||||
expect(overview).toContain("enabled={drawer.activeTab() === 'overview'}");
|
||||
expect(overview).toContain('onRangeChange={drawer.setMetricsHistoryRange}');
|
||||
const panel = read('frontend-modern/src/components/Workloads/GuestDrawerHistory.tsx');
|
||||
expect(panel).toContain('label="History range"');
|
||||
expect(panel).toContain('point.min ?? point.value');
|
||||
expect(panel).toContain('point.max ?? point.value');
|
||||
expect(panel).toContain('average, ${low} to ${high}');
|
||||
});
|
||||
|
||||
it('explains stored buckets and peaks without inventing coverage or an incident time', () => {
|
||||
const text = prose(history());
|
||||
expect(text).toContain('22% average, 10% to 95%');
|
||||
expect(text).toContain('does not rule out the recorded 95% peak');
|
||||
expect(text).toContain('does not say how long that peak lasted');
|
||||
expect(text).toContain('does not prove that usage stayed constant');
|
||||
const rows = [...history().querySelectorAll('tbody tr')];
|
||||
const band = rows.find((row) => prose(row).startsWith('Shaded low–high band'))!;
|
||||
const peak = rows.find((row) => prose(row).startsWith('peak while inspecting'))!;
|
||||
expect(prose(band)).toContain('Not continuous coverage, every original sample');
|
||||
expect(prose(peak)).toContain('Not necessarily the highest value');
|
||||
expect(prose(peak)).toContain("alert's exact time");
|
||||
expect(text).toContain('Missing is not measured zero');
|
||||
expect(text).toContain('Window start and Window end bound the requested interval');
|
||||
expect(text).toContain('not the first and last successful observations');
|
||||
});
|
||||
|
||||
it('keeps both existing bookmarks and the new cross-guide links usable', () => {
|
||||
for (const [element, name, fragment] of [
|
||||
[pbs(), 'METRICS_HISTORY', 'read-a-history-panel'],
|
||||
[history(), 'PBS', 'pbs-is-connected-but-history-stays-empty'],
|
||||
] as const) {
|
||||
expect(element.querySelector(`a[href="/docs/${name}#${fragment}"]`)).not.toBeNull();
|
||||
expect(render(name).querySelector(`#${fragment}`)).not.toBeNull();
|
||||
}
|
||||
});
|
||||
|
||||
it('retains the safe no-replay and private-evidence investigation path', () => {
|
||||
expect(prose(pbs())).toContain('Do not edit or replay the request');
|
||||
expect(prose(pbs())).toContain('Do not refresh or restart the server');
|
||||
expect(prose(pbs())).toContain('Do not share a HAR export');
|
||||
expect(prose(pbs())).toContain('Do not delete and re-add connections');
|
||||
expect(prose(history())).toContain('do not run Diagnostics or guest-agent probes');
|
||||
expect(prose(history())).toContain('not chart inspection');
|
||||
expect(
|
||||
history().querySelector('a[href="/docs/VM_DISK_MONITORING#backup-safety"]'),
|
||||
).not.toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user