mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-26 13:39:47 +00:00
Integrate reviewed stored-chart navigation and peak help
Accept exact PI commitsc670f6b6and647664b6: correct existing PBS and metrics guides, preserve shipped mirrors and bookmarks, and retain source-bound Docs/browser proof. Documentation maintenance adds no product surface. 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.
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"version": 1,
|
||||
"result": "passed",
|
||||
"base_sha": "c670f6b6666e6f91241e6ba2e20f77b768c3bc1e",
|
||||
"changed_paths": [
|
||||
"frontend-modern/public/docs/PBS.md",
|
||||
"frontend-modern/public/docs/METRICS_HISTORY.md"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/public/docs/PBS.md": "a4e7aa00bf32f8269a20f8f1c3609214d8dadb1da79a3ed0e7b4b980789741cf",
|
||||
"frontend-modern/public/docs/METRICS_HISTORY.md": "24d00753afb3bc8a15f079958d6fcb964cecfbfcf14f2f9e42e8916be5fd8250"
|
||||
},
|
||||
"routes": [
|
||||
"/docs/PBS#pbs-is-connected-but-history-stays-empty",
|
||||
"/docs/METRICS_HISTORY#read-a-history-panel"
|
||||
],
|
||||
"states": [
|
||||
"Actual canonical/shipped Markdown through production Docs and sanitised renderer in a Vite source preview; only local security/API GET fixtures.",
|
||||
"PBS host Overview chart/range versus old installed History tab, VM/datastore and Alerts History.",
|
||||
"Stored observation/window semantics and aggregated averages/minimum/maximum/local peaks without continuous-coverage or incident-time claims."
|
||||
],
|
||||
"interactions": [
|
||||
"Desktop keyboard Enter and390px WebKit touch follow both cross-guide links to existing bookmarks.",
|
||||
"Scroll to bounds/peak rows and worked example in the real article. Actual served Markdown hashes match their committed producers."
|
||||
],
|
||||
"viewports": [
|
||||
{
|
||||
"width": 1440,
|
||||
"height": 1000
|
||||
},
|
||||
{
|
||||
"width": 390,
|
||||
"height": 844
|
||||
}
|
||||
],
|
||||
"verified_at": "2026-10-14T00:23:19.647Z",
|
||||
"runtime": {
|
||||
"playwright": "1.56.1",
|
||||
"chromium": "141.0.7390.37",
|
||||
"webkit": "26.0"
|
||||
},
|
||||
"pixel_review": {
|
||||
"tool": "native view_image",
|
||||
"opened": [
|
||||
"chromium-pbs-navigation.jpg",
|
||||
"chromium-history-navigation.jpg",
|
||||
"chromium-bucket-bounds.jpg",
|
||||
"chromium-peak-example.jpg",
|
||||
"webkit-pbs-navigation.jpg",
|
||||
"webkit-history-navigation.jpg",
|
||||
"webkit-bucket-bounds.jpg",
|
||||
"webkit-peak-example.jpg"
|
||||
],
|
||||
"observations": [
|
||||
"Desktop: revised PBS host route, old-tab compatibility, Overview/range guidance and both cross-guide links are readable; the complete bounds/peak table fits the page.",
|
||||
"390 px WebKit: new navigation and no-upgrade/no-restart caveat wrap within the page. All three columns of the bounds/peak rows remain readable without page overflow, and the22% average/95% peak example and its duration/constant-usage limits are visible.",
|
||||
"Desktop bucket-bounds capture is byte-identical to the already presented history-navigation image; that same presented pixel content covers both cases.",
|
||||
"Keyboard Enter and phone touch followed both preserved bookmarks in both directions. No API, guest, backup, credential or installed monitoring operation was performed."
|
||||
],
|
||||
"remaining": null
|
||||
},
|
||||
"browser_cleanup": {
|
||||
"closed": true,
|
||||
"preview_exit": 143,
|
||||
"preview_signal": null
|
||||
},
|
||||
"evidence": "PI OUTCOME.md/RECEIPTS.md/BROWSER.json and eight retained native-inspected captures bind ten consuming cases to c670f6b6. Does not establish native guest/PBS recovery, installed acceptance, protected delivery or release availability."
|
||||
}
|
||||
@@ -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