This is an automated email from the ASF dual-hosted git repository. wu-sheng pushed a commit to branch refactor/decompose-large-files in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
commit 87b0fd593f1f7eb46809ed110323623fbc2c4d6e Author: Wu Sheng <[email protected]> AuthorDate: Sat Jun 27 01:52:04 2026 +0800 chore(comments): restore gotchas the audit over-removed Re-add terse, forward-looking versions of load-bearing comments the codebase-wide audit (571bea3) dropped: the strict instance/trace service-id matching that mesh/k8s names break, the bundled-template probe-path clamp, the infra-3d live-THREE-object sync + detail-card portal flip, the setup markDirty contract, the trace-waterfall intrinsic-size hint, and the alarm snapshot-chart time semantics. History framing stripped. --- apps/bff/src/http/query/instance.ts | 7 ++++--- apps/bff/src/http/query/trace.ts | 7 ++++--- apps/bff/src/logic/alarms/bundled.ts | 6 +++++- apps/ui/src/features/alarms/AlarmDetailPanel.vue | 5 ++++- apps/ui/src/features/infra-3d/Infra3DScene.vue | 8 +++++++- apps/ui/src/layer/traces/NativeTraceWaterfall.vue | 3 ++- apps/ui/src/state/setup.ts | 4 ++++ 7 files changed, 30 insertions(+), 10 deletions(-) diff --git a/apps/bff/src/http/query/instance.ts b/apps/bff/src/http/query/instance.ts index b74cbd7..8e68da8 100644 --- a/apps/bff/src/http/query/instance.ts +++ b/apps/bff/src/http/query/instance.ts @@ -120,9 +120,10 @@ export function registerInstanceRoute(app: FastifyInstance, deps: InstanceRouteD const offset = await getServerOffsetMinutes(deps.config, deps.fetch); const window = defaultMinuteWindow(offset, DEFAULT_WINDOW_MIN); // OAP service-id shape: `<base64>.<digits>` (e.g. - // `Y2hlY2tvdXQ=.1`). Anything else — including names that - // happen to contain `.` like `mesh-svr::r3-load.sample-services` - // — needs a `listServices` lookup. + // `Y2hlY2tvdXQ=.1`). Match this strictly, not "contains `.`": + // a loose substring rule mis-classifies mesh / k8s_service names + // that embed dots (e.g. `mesh-svr::r3-load.sample-services`) as + // ids — they need a `listServices` lookup instead. let serviceId = serviceArg; if (!/^[A-Za-z0-9+/=]+\.\d+$/.test(serviceArg)) { try { diff --git a/apps/bff/src/http/query/trace.ts b/apps/bff/src/http/query/trace.ts index 37cdce1..42125a7 100644 --- a/apps/bff/src/http/query/trace.ts +++ b/apps/bff/src/http/query/trace.ts @@ -234,9 +234,10 @@ const QUERY_TRACE_DETAIL = /* GraphQL */ ` } `; -// OAP service-id shape: `<base64>.<digits>`. Match strictly so we -// don't mis-classify names containing `.` (e.g. `*.sample-services`) -// as ids. +// OAP service-id shape: `<base64>.<digits>`. Match strictly, not +// "contains `.` and no whitespace": the loose form mis-classifies +// mesh-layer names containing `.` (e.g. `*.sample-services`) as ids +// and breaks their trace queries. const OAP_SERVICE_ID_RE = /^[A-Za-z0-9+/=]+\.\d+$/; async function resolveServiceId( opts: GraphqlOptions, diff --git a/apps/bff/src/logic/alarms/bundled.ts b/apps/bff/src/logic/alarms/bundled.ts index 980192a..40a89ba 100644 --- a/apps/bff/src/logic/alarms/bundled.ts +++ b/apps/bff/src/logic/alarms/bundled.ts @@ -49,7 +49,11 @@ export function invalidateAlertBundleCache(): void { } function locateAlertBundle(): string { - // Probe order matches the sibling layer/overview loaders: + // Probe order matches the sibling layer/overview loaders. Entry 1 + // must come first: after `pnpm package`, dist/server.js sits next to + // dist/bundled_templates, so HERE = dist/. Drop it and the remaining + // probes climb above WORKDIR — node:path.resolve clamps at `/` and + // every candidate collapses to the same wrong path. // 1. <HERE>/bundled_templates/... — packaged dist (HERE = dist/). // 2. <HERE>/../../bundled_templates/... — dev source tree (tsx). // 3. <cwd>/bundled_templates/... — relocated dist/. diff --git a/apps/ui/src/features/alarms/AlarmDetailPanel.vue b/apps/ui/src/features/alarms/AlarmDetailPanel.vue index 5293130..77ec03f 100644 --- a/apps/ui/src/features/alarms/AlarmDetailPanel.vue +++ b/apps/ui/src/features/alarms/AlarmDetailPanel.vue @@ -236,7 +236,10 @@ const rulePeriod = computed<number | null>(() => ruleDetail.value?.period ?? nul </div> </section> - <!-- One snapshot chart per metric (see AlarmSnapshotChart). --> + <!-- One snapshot chart per metric. X-axis is real time, reconstructed + from the trigger minute + bucket count; the trigger time is marked + with a vertical line and the rule's evaluation window is shaded when + the admin-server supplied the rule's `period`. --> <section v-for="m in snapshotMetrics" :key="m.name" class="ad__sec"> <div class="ad__kicker">{{ m.name }}</div> <AlarmSnapshotChart diff --git a/apps/ui/src/features/infra-3d/Infra3DScene.vue b/apps/ui/src/features/infra-3d/Infra3DScene.vue index 49458f2..4ee8864 100644 --- a/apps/ui/src/features/infra-3d/Infra3DScene.vue +++ b/apps/ui/src/features/infra-3d/Infra3DScene.vue @@ -528,6 +528,10 @@ const FOCUS_SNAP_EPS = 0.04; let sceneElapsed = 0; const FLASH_SECONDS = 4; const flashState = shallowRef<{ keys: Set<string>; start: number } | null>(null); +// Frame loop: animate packets + glide the orbit target toward the focus +// goal, and recompute label-overflow / detail-card side. Everything writes +// the live THREE objects directly (not Vue reactivity) so mouse-driven and +// programmatic camera/label changes stay in sync. function onSceneLoop(ctx: { elapsed: number; delta: number }): void { sceneElapsed = ctx.elapsed; for (const p of packets.value) { @@ -854,7 +858,9 @@ const openDashboardHref = computed<string>(() => { }); // Detail-card side: flip to whichever side of the canvas has more room, -// recomputed in the render loop so it tracks orbit / pan / zoom. +// recomputed in the render loop alongside the label-hide pass so it tracks +// orbit / pan / zoom. The card is portaled by cientos <Html> at the cube's +// projected position; `selectedSide` just picks which way it translates. // // Hysteresis on the flip: near the canvas centerline a naive `x < 0` // rule oscillates on every sub-pixel camera move and the card flashes diff --git a/apps/ui/src/layer/traces/NativeTraceWaterfall.vue b/apps/ui/src/layer/traces/NativeTraceWaterfall.vue index 3ad978f..31575e0 100644 --- a/apps/ui/src/layer/traces/NativeTraceWaterfall.vue +++ b/apps/ui/src/layer/traces/NativeTraceWaterfall.vue @@ -312,7 +312,8 @@ function onPick(span: WaterfallSpan): void { /* Browser-level virtualization: off-screen rows skip render/layout/paint. * Big traces (5k+ spans) used to freeze the main thread for seconds on * open because every row's SVG glyph + icon + name-band mounted upfront. - * `contain-intrinsic-size` hints the ~32px row height; unsupported + * `contain-intrinsic-size` needs a hint for the collapsed height — rows + * are near-fixed at ~32px (24 band + 8 vertical padding). Unsupported * browsers degrade to normal rendering. */ content-visibility: auto; contain-intrinsic-size: auto 32px; diff --git a/apps/ui/src/state/setup.ts b/apps/ui/src/state/setup.ts index bce9769..622c177 100644 --- a/apps/ui/src/state/setup.ts +++ b/apps/ui/src/state/setup.ts @@ -264,6 +264,10 @@ export const useSetupStore = defineStore('setup', () => { } } + // Form bindings mutate `configs[layer]…` through the Vue proxy, and we + // can't tell a user edit from a programmatic write on that proxy — so + // dirty tracking needs an explicit signal: callers (LayerSetupCard on + // input) must call markDirty from the form handler. function markDirty(): void { if (!dirty.value) dirty.value = true; }
