wu-sheng opened a new pull request, #14:
URL: https://github.com/apache/skywalking-horizon-ui/pull/14
Adds OAP 10's cross-layer service hierarchy to every per-layer service
map as a focus + context + suggestions overlay, plus a deep-link
validator that closes the gap left by landing's top-N rollup.
## What
Picking a service in the topology fires a lazy `getServiceHierarchy`
probe (one round-trip). If the service has cross-layer peers, a small
chevron-stack chip clips to the focused hex's right edge.
Click the chip → the topology dims under a transparent canvas; the
focused hex re-renders bright at the **exact same screen position and
scale** as the underlying hex (the d3 zoom transform is mirrored onto
the overlay), and peers fan vertically from the focus column.
Layer ordering matches booster-ui's `computeHierarchyLevels()` rule:
sort by OAP `level` DESC with alphabetical tiebreak. So with focus in
MESH, GENERAL (also level 3, alphabetically first) sits **above**,
MESH_DP (level 1) below, K8S_SERVICE (level 0) further below.
While the overlay is open the global auto-refresh ticker is suspended
so the background topology + KPI panels don't shift mid-explore.
Closing (`×` button, ESC, or click-on-dim) resumes the ticker and
fires one immediate tick so the page snaps back to live data.
## Peer navigation — two-step open
1. **First click** on a peer hex arms it: selection halo + side
``↗ Open in <Layer>`` action chip.
2. **Second click** on the action chip opens the destination layer in
a **new browser tab** with the peer service pre-selected via
``?service=<id>``. ``noopener`` so the new tab can't reach back
into the source.
3. Peers in layers Horizon has **no template** for render dimmed with
``cursor: not-allowed``; clicking surfaces *"No layer template
configured for <Layer>"* in the event log instead.
## Deep-link service validation
A new ``GET /api/layer/:key/services`` endpoint returns the layer's
full roster from the BFF's existing 60s catalog snapshot — **no extra
OAP traffic**, all callers reuse the same single-flight fan-out the
sidebar counts already use.
On every per-layer page entry the shell validates the URL-pinned
``?service=<id>`` against this roster:
- **Present** → trust the pick, even if landing's top-N rollup
doesn't sample it. This is the case for every low-traffic
hierarchy-peer click — previously the dashboard silently swapped
the operator's pick for ``rows[0]``, leaving the URL bar clean and
the in-memory service "jumping" to something else.
- **Absent** → pop a *"Service not found in this layer"* modal with
the offending id and a one-click **Use <first-available>** button;
Dismiss leaves the operator on the empty view.
The dashboard view's ``serviceName`` resolution now consults the
roster after landing's top-N, so the cascade ``landing → serviceName
→ instances → first instance`` completes for any valid service. The
old aggressive *URL-not-in-landing → overwrite* fallback is removed
(its sole legitimate use — stale-bookmark recovery — is now handled
honestly by the modal).
## Files
| Area | Files |
|---|---|
| BFF | ``apps/bff/src/logic/oap/hierarchy.ts``,
``apps/bff/src/http/query/services.ts``,
``apps/bff/src/http/query/topology.ts`` (+ ``service-hierarchy`` route),
``apps/bff/src/rbac/route-policy.ts``, ``apps/bff/src/server.ts`` |
| API client | ``packages/api-client/src/service-hierarchy.ts``,
``packages/api-client/src/index.ts``, ``apps/ui/src/api/scopes/layer.ts`` |
| UI overlay |
``apps/ui/src/layer/service-map/ServiceHierarchyOverlay.vue``,
``hierarchyStore.ts``, ``useServiceHierarchy.ts``, ``LayerServiceMapView.vue`` |
| Validator | ``apps/ui/src/layer/useLayerServices.ts``,
``apps/ui/src/layer/LayerShell.vue``,
``apps/ui/src/render/layer-dashboard/LayerDashboardsView.vue`` |
| Docs | ``CHANGELOG.md`` |
## Validation
Walked through every path against the public demo OAP
(``demo.skywalking.apache.org``):
- ``agent::songs`` (GENERAL) → 3 peers: K8S_SERVICE, MESH_DP, MESH —
chip appears, overlay opens with all three lanes correctly ordered.
- ``agent::recommendation`` chip → arm → ``↗ Open in Istio Data
Plane`` → new tab to ``/layer/mesh_dp/instance?service=<id>``;
destination validates against roster (present), resolves name from
roster (landing top-N missed it), cascade picks first sidecar,
widgets render.
- Manually mangled id in ``?service=`` → modal pops with the bad id +
fallback offer; *Use <first>* picks correctly, *Dismiss* leaves the
empty view honest.
Typecheck clean across BFF / api-client / UI; ``license-eye`` clean.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]