This is an automated email from the ASF dual-hosted git repository. wu-sheng pushed a commit to branch feat/service-internal-topology in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
commit a7258e13f35745d94158ed03c519da615379c73d Author: Wu Sheng <[email protected]> AuthorDate: Tue Jun 9 15:45:52 2026 +0800 feat(menu): config-driven excluded layers (horizon.yaml layers.excluded) Replaces the removed hard-coded hide list with an operator-configurable `layers.excluded` block. Each entry is { key, reason? }; the menu drops those layers from the sidebar (both live + OAP-down paths), matched case-insensitively. Defaults to FaaS (deprecated) and Virtual Gateway (not planned to set up); documented in horizon.example.yaml. Clear the list to surface every reported layer. --- apps/bff/src/config/schema.ts | 26 ++++++++++++++++++++++++++ apps/bff/src/http/query/menu.ts | 14 ++++++++++---- horizon.example.yaml | 14 ++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/apps/bff/src/config/schema.ts b/apps/bff/src/config/schema.ts index 0aea48f..ed17d7c 100644 --- a/apps/bff/src/config/schema.ts +++ b/apps/bff/src/config/schema.ts @@ -319,9 +319,35 @@ const querySchema = z .strict() .default({ landingServiceCap: 100 }); +// Layers hidden from the sidebar / menu even when OAP reports them in +// `listLayers`. Config-driven (replaces a former hard-coded hide list): an +// operator can clear `excluded` to surface every reported layer, or add keys +// for internal-only layers they don't want on the menu. The `reason` is +// documentation for whoever reads this file — it isn't shown in the UI (an +// excluded layer simply doesn't appear). +const excludedLayerSchema = z + .object({ + /** OAP layer key (UPPER_SNAKE), matched case-insensitively. */ + key: z.string().min(1), + /** Why it's hidden — operator-facing note, not surfaced in the UI. */ + reason: z.string().optional(), + }) + .strict(); +const DEFAULT_EXCLUDED_LAYERS = [ + { key: 'FAAS', reason: 'Deprecated.' }, + { key: 'VIRTUAL_GATEWAY', reason: 'Not planned to set up.' }, +]; +const layersSchema = z + .object({ + excluded: z.array(excludedLayerSchema).default(DEFAULT_EXCLUDED_LAYERS), + }) + .strict() + .default({ excluded: DEFAULT_EXCLUDED_LAYERS }); + export const configSchema = z .object({ server: serverSchema.default({}), + layers: layersSchema, oap: oapSchema.default({}), auth: authSchema, rbac: rbacSchema, diff --git a/apps/bff/src/http/query/menu.ts b/apps/bff/src/http/query/menu.ts index ebd7fb6..c4965fd 100644 --- a/apps/bff/src/http/query/menu.ts +++ b/apps/bff/src/http/query/menu.ts @@ -338,6 +338,12 @@ export function registerMenuRoute(app: FastifyInstance, deps: MenuRouteDeps): vo const queryUrl = cfg.oap.queryUrl; const opts = buildOapOpts(cfg, deps.fetch); const locale = localeFromRequest(req); + // Operator-configured hidden layers (horizon.yaml `layers.excluded`). + // Defaults to FaaS (deprecated) + Virtual Gateway (not planned). Matched + // case-insensitively against the canonical layer key. + const excludedLayers = new Set( + (cfg.layers?.excluded ?? []).map((e) => e.key.toUpperCase()), + ); try { const raw = await graphqlPost<MenuRaw>(opts, MENU_QUERY); @@ -392,10 +398,10 @@ export function registerMenuRoute(app: FastifyInstance, deps: MenuRouteDeps): vo // Every layer OAP surfaces in `listLayers` is shown — including // ones with no Horizon template (they render with default caps, a - // bare Service page). Disabled-in-admin layers are the only drop: - // they're soft-deleted (matches how disabled overviews vanish). + // bare Service page). Dropped only when admin-disabled (soft-deleted, + // like disabled overviews) or config-excluded (`layers.excluded`). const layers = ordered - .filter((key) => !disabled.has(key)) + .filter((key) => !disabled.has(key) && !excludedLayers.has(key.toUpperCase())) .map((key) => deriveLayer( key, @@ -428,7 +434,7 @@ export function registerMenuRoute(app: FastifyInstance, deps: MenuRouteDeps): vo const emptyRows = new Map<string, TemplateRow>(); for (const rawKey of Object.keys(LAYER_DEFAULTS)) { const key = canonical(rawKey); - if (seen.has(key)) continue; + if (seen.has(key) || excludedLayers.has(key.toUpperCase())) continue; seen.add(key); layers.push(deriveLayer(key, false, null, -1, null, locale, emptyRows, null)); } diff --git a/horizon.example.yaml b/horizon.example.yaml index 07780ed..05984c8 100644 --- a/horizon.example.yaml +++ b/horizon.example.yaml @@ -24,6 +24,20 @@ server: host: 127.0.0.1 port: 8081 +# Layers hidden from the sidebar even when OAP reports them in listLayers. +# Config-driven — there is no hard-coded hide list. Clear `excluded` to +# surface every reported layer, or add keys for internal-only layers you +# don't want on the menu. `reason` is a note for whoever reads this file; +# it is NOT shown in the UI (an excluded layer simply doesn't appear). +# Keys are OAP layer keys (UPPER_SNAKE), matched case-insensitively. +# The defaults below are applied when this block is omitted entirely. +layers: + excluded: + - key: FAAS + reason: Deprecated. + - key: VIRTUAL_GATEWAY + reason: Not planned to set up. + oap: # OAP query host (port 12800 by default; GraphQL + /status/*). One URL # because query traffic is load-balanceable — any OAP node can answer.
