This is an automated email from the ASF dual-hosted git repository.

wu-sheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git


The following commit(s) were added to refs/heads/main by this push:
     new 65374bf  ui events: fix missed start edge + add config-resolution step
65374bf is described below

commit 65374bf51c774b5d0c269f7c5a67db6e5e4df002
Author: Wu Sheng <[email protected]>
AuthorDate: Sun May 17 11:53:51 2026 +0800

    ui events: fix missed start edge + add config-resolution step
    
    Two fixes so the ticker shows the full page-assembly sequence
    (config → service → instance/endpoint → widget):
    
    1. useQueryEvents missed the rising edge when vue-query flipped
       isFetching synchronously during the surrounding useQuery() call
       (the query is auto-fired the moment `enabled` is truthy, before
       the watch attaches). Now we snapshot the mount-time state
       explicitly: in-flight → retroactive `start`; cache hit → one-shot
       `info`; empty → wait for the watch's first transition. That's why
       so11y_java_agent's instance call surfaced "Loaded N" but never
       "Loading…".
    
    2. useLayerDashboardConfig now emits a `config` event the moment its
       bundle/network resolution resolves, so the ticker reports
       "instance dashboard config ready · 7 widgets (preloaded)" at the
       top of the page-assembly chain.
---
 apps/ui/src/controls/useQueryEvents.ts             | 21 ++++++++++-----
 .../render/layer-dashboard/useLayerDashboard.ts    | 30 ++++++++++++++++++++--
 2 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/apps/ui/src/controls/useQueryEvents.ts 
b/apps/ui/src/controls/useQueryEvents.ts
index 1b3a32d..ce685b3 100644
--- a/apps/ui/src/controls/useQueryEvents.ts
+++ b/apps/ui/src/controls/useQueryEvents.ts
@@ -57,15 +57,24 @@ export function useQueryEvents<T>(
   q: QueryLike<T>,
   labels: QueryEventLabels<T>,
 ): void {
-  // Cache-hit echo — when the composable mounts and the query already
-  // has data, emit an info line so the ticker doesn't go silent on
-  // fast-path revisits.
-  if (labels.cached && q.data.value !== undefined && !q.isFetching.value) {
+  // Snapshot the mount-time state. vue-query can flip `isFetching`
+  // synchronously during the surrounding `useQuery(...)` call (the
+  // query is auto-fired the moment `enabled` is truthy), so by the
+  // time this composable runs we may have already missed the
+  // false→true edge. Cover the three possible initial states
+  // explicitly:
+  //   - in-flight  ⇒ retroactive `start` (the watch below will then
+  //                    pick up the matching falling edge as `ok`/`err`).
+  //   - cache hit  ⇒ one-shot `info` line so the ticker doesn't go
+  //                    silent on fast-path revisits.
+  //   - empty       ⇒ no event yet; the watch will catch the upcoming
+  //                    rising edge once the query actually fires.
+  if (q.isFetching.value) {
+    pushEvent(topic, 'start', labels.start());
+  } else if (labels.cached && q.data.value !== undefined) {
     pushEvent(topic, 'info', labels.cached(q.data.value));
   }
 
-  // Fetch in-flight — push `start` on rising edge, push `ok`/`err`
-  // on falling edge based on whether the result is an error.
   watch(
     () => q.isFetching.value,
     (now, before) => {
diff --git a/apps/ui/src/render/layer-dashboard/useLayerDashboard.ts 
b/apps/ui/src/render/layer-dashboard/useLayerDashboard.ts
index 39acda3..8311ce1 100644
--- a/apps/ui/src/render/layer-dashboard/useLayerDashboard.ts
+++ b/apps/ui/src/render/layer-dashboard/useLayerDashboard.ts
@@ -27,9 +27,10 @@
  * viewed service is instant.
  */
 
-import { computed, type Ref } from 'vue';
+import { computed, watch, type Ref } from 'vue';
 import { useQuery } from '@tanstack/vue-query';
 import { useQueryEvents } from '@/controls/useQueryEvents';
+import { pushEvent } from '@/controls/eventLog';
 import { useAutoRefreshSubscribe } from 
'../../controls/useAutoRefreshSubscribe';
 import { bffClient } from '@/api/client';
 import {
@@ -63,8 +64,33 @@ export function useLayerDashboardConfig(layerKey: 
Ref<string>, scope?: Ref<strin
   });
   useAutoRefreshSubscribe(() => q.refetch());
 
+  const config = computed(() => bundled.value ?? q.data.value ?? null);
+  // Surface the config-resolution step in the event ticker so the
+  // operator sees the page-assembly sequence start at the very top
+  // (config → services → instances/endpoints → widgets). The bundle
+  // hit fires the moment localStorage resolves; the network fallback
+  // gets its own start/ok event via useQueryEvents below.
+  let configReported = false;
+  watch(
+    config,
+    (c) => {
+      if (!c || configReported) return;
+      const s = (scope?.value ?? 'service') as string;
+      const widgetN = c.widgets?.length ?? 0;
+      const source = bundled.value ? 'preloaded' : 'network';
+      pushEvent('config', 'info', `${s} dashboard config ready · ${widgetN} 
widget${widgetN === 1 ? '' : 's'} (${source})`);
+      configReported = true;
+    },
+    { immediate: true },
+  );
+  useQueryEvents('config-net', q, {
+    start: () => `Fetching ${scope?.value ?? 'service'} dashboard config for 
${layerKey.value}…`,
+    ok: () => `Dashboard config loaded from BFF`,
+    err: (e) => `Dashboard config fetch failed: ${e instanceof Error ? 
e.message : String(e)}`,
+  });
+
   return {
-    config: computed(() => bundled.value ?? q.data.value ?? null),
+    config,
     isLoading: computed(() => !loaded.value && q.isLoading.value),
     error: q.error,
   };

Reply via email to