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 cbe83cf ui events: per-widget result events after the dashboard batch
returns
cbe83cf is described below
commit cbe83cf6e4b17e522b56c431ae51dee23c973d63
Author: Wu Sheng <[email protected]>
AuthorDate: Sun May 17 12:01:44 2026 +0800
ui events: per-widget result events after the dashboard batch returns
After the orchestrator's step 6 ("widgets rendered M/N") fires, emit
one info / ok / err event per widget in the batch — labelled by the
widget's title (from the config bundle) and tagged with what came
back: a scalar value, N series, top-N items, or an explicit error /
"no data". Topic is `widget/<widget-id>` so paired starts (none —
the batch fires once at the dashboard step) and any future per-
widget refetches dedup correctly per id.
Operator can now scan the EventTicker history and tell at a glance
which specific widget MQE landed and which came back empty without
having to scroll the grid looking for blank cards.
---
.../layer-dashboard/useLayerPageOrchestrator.ts | 46 +++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
b/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
index 6b82d3a..703fe18 100644
--- a/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
+++ b/apps/ui/src/render/layer-dashboard/useLayerPageOrchestrator.ts
@@ -69,7 +69,16 @@ export interface OrchestratorRefs {
endpointList: Ref<ReadonlyArray<{ id: string; name: string }>>;
effectiveEndpoint: Ref<string | null>;
/** Dashboard response — widgets rendered. */
- dashboard: Ref<{ widgets?: Array<{ error?: string; value?: unknown; series?:
unknown[]; topList?: unknown[]; topGroups?: unknown[] }> } | null>;
+ dashboard: Ref<{
+ widgets?: Array<{
+ id: string;
+ error?: string;
+ value?: unknown;
+ series?: unknown[];
+ topList?: unknown[];
+ topGroups?: unknown[];
+ }>;
+ } | null>;
}
type Phase =
@@ -242,6 +251,41 @@ export function useLayerPageOrchestrator(refs:
OrchestratorRefs): {
report('dashboard', `Step 6 · widgets rendered · ${withData}/${total}
with data`);
stamps.dashboard = true;
done.value = true;
+
+ // After the batch dashboard returns, emit a per-widget event
+ // for every result so the EventTicker shows which widget got
+ // data, which came back empty, and which errored. The dashboard
+ // query is batched server-side (one GraphQL trip for all MQEs)
+ // so these are post-hoc info events, not separate fetches —
+ // they let the operator pinpoint a specific widget's status
+ // without staring at the rendered grid.
+ const cfgWidgets = (refs.config.value?.widgets ?? []) as Array<{ id?:
string; title?: string }>;
+ const titleById = new Map<string, string>();
+ for (const cw of cfgWidgets) {
+ if (cw?.id) titleById.set(cw.id, cw.title ?? cw.id);
+ }
+ for (const r of widgets) {
+ const label = titleById.get(r.id) ?? r.id;
+ let kind: 'ok' | 'err' | 'info' = 'info';
+ let detail = 'no data';
+ if (r.error) {
+ kind = 'err';
+ detail = `error: ${r.error}`;
+ } else if (r.value != null) {
+ kind = 'ok';
+ detail = `value ${r.value}`;
+ } else if (Array.isArray(r.series) && r.series.length > 0) {
+ kind = 'ok';
+ detail = `${r.series.length} series`;
+ } else if (Array.isArray(r.topList) && r.topList.length > 0) {
+ kind = 'ok';
+ detail = `top ${r.topList.length}`;
+ } else if (Array.isArray(r.topGroups) && r.topGroups.length > 0) {
+ kind = 'ok';
+ detail = `${r.topGroups.length} group${r.topGroups.length === 1 ? ''
: 's'}`;
+ }
+ pushEvent(`widget/${r.id}`, kind, `Widget ${label} · ${detail}`);
+ }
},
{ immediate: true },
);