From 3414a5abdad055f99192d44fc4d11becc6d73d7a Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 26 Aug 2026 12:45:53 +0100 Subject: [PATCH] Use host history for explicit Docker targets --- .../subsystems/frontend-primitives.md | 5 ++-- frontend-modern/browser-verification.json | 22 ++++++++---------- ...ourceDetailDrawer.machine-history.test.tsx | 23 +++++++++++++++++++ ...rMetricsHistoryModel.branchcov0712.test.ts | 21 +++++++++++++++++ ...resourceDetailDrawerMetricsHistoryModel.ts | 6 ++++- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index aad133b10..b753b92b3 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -6391,8 +6391,9 @@ when at least one current machine has finite utilization evidence, so estates without GPU telemetry do not carry an empty default column or an inert toggle. The shared resource drawer keeps `GuestDrawerHistory` as the sole history -renderer. Agent-backed hosts, including standalone Unraid machines, Proxmox -nodes, and Docker/Podman hosts, consume the single +renderer. Agent-backed hosts and explicit `docker-host` metrics targets, +including standalone Unraid machines, Proxmox nodes, and Docker/Podman hosts, +consume the single `frontend-modern/src/components/shared/hostMetricsHistoryModel.ts` `HOST_METRICS_HISTORY_GROUPS` catalog so CPU temperature history cannot drift out of one host surface while remaining on another. Host resources provide the diff --git a/frontend-modern/browser-verification.json b/frontend-modern/browser-verification.json index c8a37df35..d17766c30 100644 --- a/frontend-modern/browser-verification.json +++ b/frontend-modern/browser-verification.json @@ -1,15 +1,15 @@ { "version": 1, - "base_sha": "5d46e7d0e76ddd069a12f62fb670fd3ec0356e9e", - "verified_at": "2026-08-26T11:27:33Z", + "base_sha": "08b8144fcff526519a8b7d7706dcc044bebf170c", + "verified_at": "2026-08-26T11:44:58Z", "result": "passed", "changed_paths": [ "frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts" ], "content_sha256": { - "frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts": "6767cf06b2f3c42931deba2b9620858210d8c7ce55d261b042e752b6680a4223" + "frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts": "63066dea7134226ea5348be26147fd433e56225b429b88854825410dba80111a" }, - "routes": ["/truenas/storage"], + "routes": ["/docker/overview"], "viewports": [ { "width": 1230, @@ -21,15 +21,13 @@ } ], "states": [ - "TrueNAS pool History with only the canonical capacity series populated", - "TrueNAS dataset History with only the canonical capacity series populated", - "TrueNAS physical-disk History at 24 hours and 7 days with activity, disk I/O, and temperature populated", - "narrow TrueNAS physical-disk History with the same populated chart catalog" + "explicit Docker host History at 24 hours with utilization, network I/O, disk I/O, and thermal series populated", + "explicit Docker host History at 7 days with the same canonical host chart catalog populated", + "narrow explicit Docker host History with the complete host chart catalog and no collecting placeholders" ], "interactions": [ - "opened archive and archive/cold from the TrueNAS storage table; each drawer rendered one populated Capacity chart and no workload-only charts", - "opened physical disk sdc and selected History; confirmed Activity, Disk I/O, and Temperature charts with zero Collecting history placeholders", - "switched the physical-disk History selector to 7 days; all three groups remained populated", - "rechecked sdc at 390 by 844; the responsive table and populated disk history remained usable" + "expanded auth-service-01 from the Docker host table and selected History; confirmed Utilization, Network I/O, Disk I/O, and Thermals with zero Collecting history placeholders", + "switched the host History selector to 7 days and back to 24 hours; all four canonical host groups remained populated", + "rechecked auth-service-01 at 390 by 844 and scrolled through Thermals; charts, range control, table rows, and page navigation remained visible and usable" ] } diff --git a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.machine-history.test.tsx b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.machine-history.test.tsx index 6d72634a8..7b0193696 100644 --- a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.machine-history.test.tsx +++ b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.machine-history.test.tsx @@ -169,6 +169,29 @@ describe('ResourceDetailDrawer machine metrics history', () => { expect(history).toHaveAttribute('data-metrics', 'disk,diskread,diskwrite,smart_temp'); }); + it('renders explicit Docker host history with the canonical host catalog', async () => { + render(() => ( + + )); + + await fireEvent.click(screen.getByRole('tab', { name: 'History' })); + + const history = screen.getByTestId('machine-history'); + expect(history).toHaveAttribute('data-resource-type', 'docker-host'); + expect(history).toHaveAttribute('data-groups', 'utilization,network,disk-io,thermals'); + expect(history).toHaveAttribute( + 'data-metrics', + 'cpu,memory,disk,netin,netout,diskread,diskwrite,temperature', + ); + }); + it('adds a first-class discovery tab for Pulse Agent machines', async () => { syncAIRuntimeSettings({ discovery_enabled: true } as Parameters< typeof syncAIRuntimeSettings diff --git a/frontend-modern/src/components/Infrastructure/__tests__/resourceDetailDrawerMetricsHistoryModel.branchcov0712.test.ts b/frontend-modern/src/components/Infrastructure/__tests__/resourceDetailDrawerMetricsHistoryModel.branchcov0712.test.ts index 69c864fe9..579e32ec3 100644 --- a/frontend-modern/src/components/Infrastructure/__tests__/resourceDetailDrawerMetricsHistoryModel.branchcov0712.test.ts +++ b/frontend-modern/src/components/Infrastructure/__tests__/resourceDetailDrawerMetricsHistoryModel.branchcov0712.test.ts @@ -288,6 +288,27 @@ describe('getResourceMetricsHistoryCurrentMetrics branch coverage', () => { expect(getResourceMetricsHistoryCurrentMetrics(resource).temperature).toBe(57.5); }); + it('uses canonical host and GPU groups for an explicit Docker host target', () => { + const resource = baseResource({ + type: 'docker-host', + metricsTarget: { resourceType: 'docker-host', resourceId: 'nebula-1-mock' }, + agent: { + sensors: { + gpu: [{ id: '0', name: 'NVIDIA A6000', utilizationPercent: 72 }], + }, + }, + }); + + expect(getResourceMetricsHistoryGroups(resource).map((group) => group.id)).toEqual([ + 'utilization', + 'network', + 'disk-io', + 'thermals', + 'gpu-utilization', + 'gpu-thermal', + ]); + }); + it('keeps workload history groups free of host-only thermals', () => { const resource = baseResource({ type: 'vm', diff --git a/frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts b/frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts index 19364a220..a42d67402 100644 --- a/frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts +++ b/frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts @@ -110,6 +110,7 @@ const getBaseMetricsHistoryGroups = ( ): GuestDrawerHistoryGroupConfig[] => { switch (resourceType) { case 'agent': + case 'docker-host': return HOST_METRICS_HISTORY_GROUPS; case 'node': return NODE_METRICS_HISTORY_GROUPS; @@ -127,7 +128,10 @@ export const getResourceMetricsHistoryGroups = ( ): GuestDrawerHistoryGroupConfig[] => { const target = getResourceMetricsHistoryTarget(resource); const baseGroups = getBaseMetricsHistoryGroups(target?.resourceType); - const supportsGPUHistory = target?.resourceType === 'agent' || target?.resourceType === 'node'; + const supportsGPUHistory = + target?.resourceType === 'agent' || + target?.resourceType === 'docker-host' || + target?.resourceType === 'node'; return supportsGPUHistory && (resource.agent?.sensors?.gpu?.length ?? 0) > 0 ? [...baseGroups, ...GPU_HISTORY_GROUPS] : baseGroups;