feat: add developer-mode startup and stack hydration timing (#1619)

* feat: add developer-mode startup and stack hydration timing

Instrument boot-to-list and detail hydration with commit-aligned milestones, truthful request stages, and destination/gateway debug duration logs so performance work is guided by measurements.

* fix: redact stack names and complete hydration request stages

Stop logging stack identifiers in containers debug timing, and record state_dispatch (plus detail fetch spans) so copied reports match the advertised stage breakdown.
This commit is contained in:
Anso
2026-07-14 17:24:25 -04:00
committed by GitHub
parent 4079cb9198
commit b70a529656
26 changed files with 2449 additions and 32 deletions
+13
View File
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { apiFetch } from '@/lib/api';
import { markMilestone } from '@/lib/hydrationTiming';
import { SENCHO_SETTINGS_CHANGED } from '@/lib/events';
import type { ImageUpdateStatus, StackUpdateInfo } from '@/types/imageUpdates';
@@ -31,6 +32,10 @@ export function useImageUpdates(activeNodeId: number | undefined) {
// discarded.
const genRef = useRef(0);
// Node the image_updates_ready milestone last fired for, so it records once
// per node session (re-firing after a node switch) rather than every poll.
const imageUpdatesReadyNodeRef = useRef<number | null | undefined>(undefined);
const refresh = useCallback(async () => {
const gen = ++genRef.current;
const targetNodeId = activeNodeId ?? null;
@@ -92,6 +97,14 @@ export function useImageUpdates(activeNodeId: number | undefined) {
};
await Promise.allSettled([fetchStatus(), fetchDetail()]);
// Background milestone: both image-update requests have settled for the
// active node. Fire once per node session, and only if this refresh still
// owns the generation (a node switch mid-flight defers to the new node).
if (genRef.current === gen && imageUpdatesReadyNodeRef.current !== targetNodeId) {
imageUpdatesReadyNodeRef.current = targetNodeId;
markMilestone('image_updates_ready');
}
}, [activeNodeId]);
// Pin the interval to the latest closure without retriggering it on