Skip to content

refactor(overview): aggregate KPI tiles server-side + retire dead template config - #98

Merged
wu-sheng merged 7 commits into
mainfrom
refactor/overview-kpi-mqe-aggregate
Jul 7, 2026
Merged

refactor(overview): aggregate KPI tiles server-side + retire dead template config#98
wu-sheng merged 7 commits into
mainfrom
refactor/overview-kpi-mqe-aggregate

Conversation

@wu-sheng

@wu-sheng wu-sheng commented Jul 7, 2026

Copy link
Copy Markdown
Member

Why

Overview KPI tiles (e.g. General services · RPM / Latency / SLA) were aggregating over only a single service instead of the whole layer — a hardcoded topN:1 — so a busy layer read far too low. Surfaced in apache/skywalking#13934 ("service metrics specific to a particular service rather than the entire system").

What

1 — Overview KPI aggregation (the fix)

  • Multi-service tiles (General / Mesh / Virtual Database·Cache·MQ·GenAI) now roll up the entire layer server-side via sum/avg(top_n(<metric>,{{topn}},DES[,attr0='<layer>'])), in one query per tile instead of a per-service fan-out (≈N× fewer OAP evals on a refreshing landing page).
  • The K8s-cluster and Istio-pilot composites stay page-side (their latest() snapshots + the label-split xds_pushes can't be top_n-rolled). {{topn}} is bounded by a new HORIZON_QUERY_OVERVIEW_TOPN (default 100).
  • Mesh's second tile is now Latency (avg response time) in place of the old P95.

2 — Page-side aggregation is now a first-class, per-widget choice

  • Explicit Aggregation mode in the editor (Server-side vs Page-side), replacing an implicit top_n-sniff. Page-side widgets carry their own limit (top-N services) and, new here, a rankBy — rank the top-N by one of the widget's KPIs (default the first) or by a separate ranking metric ({ "kpi": n } | { "mqe": "…" }). Fixes a latent bug where a page-side widget's first KPI being a LABELED_VALUE metric (Istio pilot's xds_pushes) skewed the ranking; pilot_summary now ranks by xDS connections.
  • Each page-side widget gets its own landing call (own limit + ranking); self-aggregating tiles still batch by layer.

3 — Editor UX

  • {{topn}} is explained inline via a WidgetTip popover showing its live resolved value (surfaced through /api/oap/info).
  • Redesigned the aggregation controls (mode radio + nested Top-N/Rank-by), denser toggles. Fixed a duplicate "mqe" option in the KPI Source selector.

4 — Cleanup (no behavior change)

  • Retired the dead legacy per-layer-overview machinery (LayerOverviewConfig / headerColumns / overviewGroups / overviewMetrics) — the standalone Overview dashboards replaced it.
  • Swept verified-dead template config (serviceCountTile, the LayerDef.header twin, LogConfig.defaultTags, LandingConfig.style, LandingColumn.tip, OverviewWidgetResult, the BFF LayerMetricsConfig alias) + dead loader migrations. No layer-template or OAP wire-contract change — only the two Overview dashboard templates (services.json, mesh.json) + their i18n overlays changed.

Rollout — Overview templates need an OAP re-sync

Overviews are served remote-only from OAP (the disk bundle is a seed, not a render-time source). Fresh installs get the change via boot-seed; an existing deployment needs an admin re-sync of the bundled Overview templates (Overview-templates admin → push-bundled). The public demo has already been synced for the aggregation fix.

Validation

  • type-check · build (UI + BFF) · lint · 356 unit tests · license · i18n:validate — all green.
  • Live OAP (public demo): every converted tile MQE validated (correct layer-wide aggregates); both landing paths (fire-once selfAggregate + page-side fan-out) confirmed; the rank-by mechanism proven on a multi-service layer (ranking by a separate metric changes the top-N selection + aggregate); top_n shown to ignore the entity normal flag (so normal:true is safe for the normal:false VIRTUAL_* layers).
  • Caveat: no bundled page-side layer has >1 service, so the client's rankBy payload assembly is type-checked + traced but not exercised in the live UI.

wu-sheng added 3 commits July 7, 2026 19:34
…plate config

Overview KPI tiles (e.g. "General services · RPM / Latency / SLA") aggregated over only a single service instead of the whole layer (a hardcoded topN:1), so a busy layer read far too low. The tiles now roll up the ENTIRE layer server-side via sum/avg(top_n(...)) — throughput summed, latency/SLA averaged — across General, Mesh, and the Virtual Database / Cache / MQ / GenAI layers, in one query per tile instead of a per-service fan-out.

The K8s-cluster and Istio-pilot composites stay page-side (their latest()/labeled metrics can't be top_n-rolled) behind an explicit `aggregateOnPage` widget flag; the top_n window is bounded by a new HORIZON_QUERY_OVERVIEW_TOPN knob (default 100). Mesh's second tile is now Latency (avg response time) in place of the old P95.

Also retires the now-dead legacy per-layer-overview machinery (LayerOverviewConfig / headerColumns / overviewGroups / overviewMetrics) — the standalone Overview dashboards replaced it — plus a sweep of verified-dead template config (serviceCountTile, the LayerDef.header twin, LogConfig.defaultTags, LandingConfig.style, LandingColumn.tip, OverviewWidgetResult, the BFF LayerMetricsConfig alias) and dead loader migrations. No layer-template or OAP wire-contract change; the tested `widgets` fallback + live component normalizers are kept.
…ggles

The Overview widget editor showed the raw `{{topn}}` placeholder in the KPI MQE field with no explanation. Add an ⓘ hint next to the MQE label that spells out what the variable is — the layer-wide top-N window the BFF substitutes at query time — and shows its live resolved value (`HORIZON_QUERY_OVERVIEW_TOPN`, surfaced via /api/oap/info). The "Show service count" and "Aggregate on page" toggles now share one row (density). Documents HORIZON_QUERY_OVERVIEW_TOPN in the container-image env-var reference.
…en-label toggles

The {{topn}} hint used a native `title` attribute — slow, unstyled, and dead on click (the exact anti-pattern WidgetTip was built to replace). Switch to WidgetTip so the tip shows a real styled popover on hover AND click/focus. Also lay the toggle rows out as checkbox-then-words (was label-stacked-above-checkbox).
@wu-sheng wu-sheng added this to the 1.0.0 milestone Jul 7, 2026
@wu-sheng wu-sheng added the bug Something isn't working label Jul 7, 2026
@wu-sheng

wu-sheng commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Synced the two updated Overview templates into the public demo OAP so the fix is live there for review:

  • horizon.overview.services + horizon.overview.mesh (source) → pushed via push-bundled; both now synced.
  • 7 mesh.i18n.* overlays (P95 → Latency label) → pushed via save-translation.

Verified the demo now serves the self-aggregating MQE (e.g. tile_general RPM = sum(top_n(service_cpm,{{topn}},DES,attr0='GENERAL'))), so the Overview "service" tiles show the whole-layer aggregate instead of a single service. See it on the Services / Mesh overview dashboards at demo.skywalking.apache.org.

Note for other deployments: because Overview templates are served remote-only from OAP, existing installs need the same one-time re-sync (Overview-templates admin → push-bundled) for the fix to take effect; fresh installs get it via the boot seed.

wu-sheng added 4 commits July 7, 2026 21:40
…der alias; clearer editor labels

Review follow-ups on the overview KPI aggregation:

- P2: the overview batched landing calls by layer and used the MAX `limit` across that layer's page-aggregated widgets, so two same-layer widgets with limits 1 and 5 were both computed over 5. Group landing calls by (layer, page-limit) so each keeps its own window. No change for the bundled dashboards (one limit per layer).

- P3: the loader stopped falling back to the legacy top-level `metrics` block for the layer header — custom/legacy templates using it would lose their header columns. Restore the `metrics`->header alias (still documented on LayerDef.metrics).

- P1 (not a bug): documented WHY the self-aggregating fragment's `entity: normal:true` is safe for VIRTUAL_* layers whose services are normal:false — `top_n` is a cross-entity scan that ignores the query entity's normal flag; verified identical results with normal:true/false against the demo.

- Editor: drop the "(fan-out)" jargon from the Aggregate-on-page toggle; add tips explaining the page-side mode and that "Top-N services" ranks by the first KPI's metric (a BFF-side sort, not a separate top_n MQE).
…selector

The Source <select> shipped two "mqe" options — one `:value="undefined"` (a
hack for KPIs with no explicit source) and one `value="mqe"` — so the dropdown
listed "mqe" twice. Bind the select to `k.source ?? 'mqe'` with an @change
writer instead, leaving a single mqe / service-count pair.
…ion mode redesign

Page-side (`aggregateOnPage`) tiles ranked the top-N services by the FIRST KPI, hardcoded — which mis-ranks when that KPI is a LABELED_VALUE metric (e.g. Istio pilot's xDS pushes). Add a `rankBy` config: `{ kpi: <index> }` to rank by another KPI, or `{ mqe: "<expr>" }` to rank by a metric not shown as a KPI. `pilot_summary` now ranks by xDS connections (a REGULAR_VALUE) instead of the labeled pushes.

Client: each page-side widget now gets its own landing call carrying its own `limit` AND ranking (self-aggregating tiles still batch by layer). This also subsumes the earlier per-(layer,limit) grouping. `rankBy.mqe` appends a ranking-only column (probed + sorted on, never displayed).

Editor: redesign the aggregation controls as an explicit **Server-side / Page-side** mode radio; the page-side params (Top-N services + Rank by) nest under it and appear only when Page-side is chosen. "Rank by" is one dropdown of the widget's KPIs + "a separate metric" (no redundant "first KPI" option). Also fixes the duplicate "mqe" option in the KPI Source selector.
The Dashboard-meta Description field was a fixed-height textarea, so a
multi-line description clipped (the tail hidden below the box). Apply the
existing `v-autosize` directive so it grows to fit its content — on the
edit drawer's meta panel and the new-dashboard modal. Same field, same
behaviour in both places.
@wu-sheng
wu-sheng merged commit d303215 into main Jul 7, 2026
8 checks passed
@wu-sheng
wu-sheng deleted the refactor/overview-kpi-mqe-aggregate branch July 7, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants