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
commit ea29dc2d1d9aee47ba1dec68df534db410dc5ed2 Author: Wu Sheng <[email protected]> AuthorDate: Thu May 21 22:15:32 2026 +0800 rbac+docs: grant overview/ttl/config reads to maintainer; doc refresh Add overview:read to viewer + maintainer defaults, and ttl:read / config:read to the maintainer + operator baselines, so the read-only Data Retention and OAP Configuration pages are reachable by monitoring roles. Document those two operate pages and refresh the docs tree (menu, customization, components, access-control, setup) for accuracy. --- apps/bff/src/config/schema.ts | 2 + apps/ui/src/shell/AppSidebar.vue | 2 +- docs/README.md | 17 ++- docs/access-control/admin-pages.md | 6 +- docs/access-control/audit-log.md | 28 +++-- docs/access-control/rbac.md | 16 +-- docs/components/charts.md | 151 ++++++-------------------- docs/components/dashboard-widgets.md | 27 +---- docs/customization/adding-a-new-layer.md | 4 +- docs/customization/layer-templates.md | 42 ++++---- docs/customization/menu-structure.md | 177 ++++++++++--------------------- docs/customization/overview-templates.md | 56 ++-------- docs/design-target.md | 4 +- docs/menu.yml | 79 +++++++------- docs/operate/cluster-metadata.md | 12 --- docs/operate/data-retention.md | 28 +++++ docs/operate/inspect.md | 2 +- docs/operate/oap-configuration.md | 24 +++++ docs/setup/audit.md | 2 +- docs/setup/auth.md | 2 +- docs/setup/debug-log.md | 2 +- docs/setup/files.md | 2 +- docs/setup/oap.md | 2 +- docs/setup/overview.md | 51 +++++++-- docs/setup/rbac.md | 13 +-- docs/setup/server.md | 2 +- docs/setup/session.md | 2 +- horizon.example.yaml | 4 + 28 files changed, 316 insertions(+), 443 deletions(-) diff --git a/apps/bff/src/config/schema.ts b/apps/bff/src/config/schema.ts index 9ac009a..0adbdd5 100644 --- a/apps/bff/src/config/schema.ts +++ b/apps/bff/src/config/schema.ts @@ -176,6 +176,7 @@ const rbacSchema = z 'logs:read', 'topology:read', 'profile:read', + 'overview:read', ], // Viewer baseline plus the platform-monitoring reads (cluster // health + OAP internals). Maintainer's whole job is watching @@ -187,6 +188,7 @@ const rbacSchema = z 'logs:read', 'topology:read', 'profile:read', + 'overview:read', 'cluster:read', 'inspect:read', 'ttl:read', diff --git a/apps/ui/src/shell/AppSidebar.vue b/apps/ui/src/shell/AppSidebar.vue index 030c117..5f862fe 100644 --- a/apps/ui/src/shell/AppSidebar.vue +++ b/apps/ui/src/shell/AppSidebar.vue @@ -354,7 +354,7 @@ watch( </RouterLink> <nav ref="navRef" class="sw-nav"> - <!-- Overviews are gated by `overview:read` (operator / admin). --> + <!-- Overviews are gated by `overview:read`. --> <template v-if="auth.hasVerb('overview:read')"> <div class="sw-nav-section sw-nav-section--icon"> <Icon :name="sectionIcon('Overviews')" /> diff --git a/docs/README.md b/docs/README.md index f098e10..cd2e4d5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,17 +6,16 @@ The sidebar on the left of this site is the canonical entry point — every sect ## How it's organized -- **Design Target** — what Horizon UI is built for and how it differs from booster-ui. -- **Compatibility** — which OAP version + modules + ports Horizon needs, and what each pane of the Cluster Status page actually probes. -- **Setup** — quick start, the container image, and a field-by-field reference for `horizon.yaml`. -- **Access Control** — local + LDAP auth, break-glass admin, the role / verb model, the audit log, and the admin pages. -- **Customization** — how the sidebar is composed from OAP layers, how to author layer dashboard and overview templates, and the end-to-end recipe for adding a new layer. -- **Components** — field-by-field reference for every widget primitive and the wrapped chart components. -- **Operate** — Cluster Status & Metadata, and the Inspect page (metric catalog + entity enumerator). +- **Setup** — quick start, container deployment, and the `horizon.yaml` settings operators usually need. +- **Compatibility** — OAP version, network ports, required modules, and cluster-status checks. +- **Operate** — Cluster Status, Data Retention, OAP Configuration, and Metrics Inspect. +- **Access Control** — local users, LDAP login, break-glass access, roles, audit log, and admin pages. +- **Customization** — layer menus, dashboard templates, overview templates, and adding a layer. +- **Reference** — design target and widget reference for template authors. ## Quick orientation -Horizon runs as two pieces: a Vue single-page app (the UI) and a Backend For Frontend (the BFF). The UI **only** talks to the BFF; the BFF is the single place that talks to OAP — query GraphQL, admin REST, and Zipkin. Every OAP-side requirement is enforced once, in the BFF, not scattered through the UI. +Horizon runs as a browser UI plus a Horizon server process. The browser talks only to the Horizon server; the server talks to OAP for query, admin, and Zipkin traffic. That keeps OAP connectivity, credentials, and compatibility checks in one place. ## Where to start, by role @@ -26,7 +25,7 @@ Horizon runs as two pieces: a Vue single-page app (the UI) and a Backend For Fro | Wiring up LDAP / configuring roles | Access Control → LDAP Backend, then RBAC. | | Customizing per-layer dashboards | Customization → Layer Dashboard Templates. | | Building a "war room" overview | Customization → Overview Templates. | -| Diagnosing a "module disabled" warning | Compatibility → Required OAP Modules and Cluster Status Check Sequence. | +| Diagnosing a "module disabled" warning | Compatibility → Required OAP Modules, then Operate → Cluster Status. | ## Live demo diff --git a/docs/access-control/admin-pages.md b/docs/access-control/admin-pages.md index f54c799..350c131 100644 --- a/docs/access-control/admin-pages.md +++ b/docs/access-control/admin-pages.md @@ -22,7 +22,7 @@ After successful login, the UI redirects to the page the user was bounced from ( ## Auth Status **Path:** `/admin/auth-status` -**Verb:** `auth:read` (maintainer, admin) +**Verb:** `auth:read` (admin by default; grant explicitly for delegated security admins) Auto-refreshes every 30 seconds. The single pane for "is my auth wiring correct?" Shows: @@ -111,7 +111,9 @@ Read-only. To change roles, edit `rbac.roles` in `horizon.yaml`; hot-reload appl | `/admin/auth-status` | `auth:read` | (none built-in; assign explicitly) | | `/admin/users` | `user:read` | (none built-in; assign explicitly) | | `/admin/roles` | `role:read` | (none built-in; assign explicitly) | -| `/admin/inspect` | `inspect:read` | maintainer, operator, admin | +| `/operate/inspect` | `inspect:read` | maintainer, operator, admin | +| `/operate/ttl` | `ttl:read` | maintainer, operator, admin | +| `/operate/config` | `config:read` | maintainer, operator, admin | `auth:read`, `user:read`, `role:read` are **not** in any default role. Either grant them via a custom role: diff --git a/docs/access-control/audit-log.md b/docs/access-control/audit-log.md index 6a008ec..125ab14 100644 --- a/docs/access-control/audit-log.md +++ b/docs/access-control/audit-log.md @@ -2,23 +2,21 @@ The audit log records sensitive operations as JSON Lines, one event per line, append-only. Configure the path via `audit.file` in `horizon.yaml` (see [Setup → audit](../setup/audit.md)). -## Event schema +## Event Fields Each event has these fields: -```ts -interface AuditEvent { - ts: string; // ISO-8601 timestamp - actor: string | null; // username; null for system events - action: string; // e.g. 'auth.login', 'rule.addOrUpdate' - verb?: string; // RBAC verb checked, if any - target?: string; // resource id / name - outcome: string; // 'success' | 'failure' | 'break-glass' | HTTP status | OAP status - details?: Record<string, unknown>; // free-form context - fromIp?: string; // requester IP - sessionId?: string; -} -``` +| Field | Meaning | +|---|---| +| `ts` | ISO-8601 timestamp. | +| `actor` | Username, or `null` for system events. | +| `action` | Operation name, such as `auth.login` or `rule.addOrUpdate`. | +| `verb` | RBAC verb checked, when applicable. | +| `target` | Resource id or name, when applicable. | +| `outcome` | `success`, `failure`, `break-glass`, or the upstream HTTP/OAP status. | +| `details` | Extra context for the operation. | +| `fromIp` | Requester IP. | +| `sessionId` | Session id, when a session exists. | One event per line, `\n`-terminated. Use `jq -c` to filter: @@ -28,7 +26,7 @@ tail -f horizon-audit.jsonl | jq -c 'select(.action | startswith("auth."))' ## Recorded actions -The recorded set evolves with the codebase. As of the current build: +The recorded set can grow between releases. In 0.5.0: | Action | Outcome values | Notes | |---|---|---| diff --git a/docs/access-control/rbac.md b/docs/access-control/rbac.md index c246390..00e8963 100644 --- a/docs/access-control/rbac.md +++ b/docs/access-control/rbac.md @@ -13,7 +13,7 @@ Sessions capture the **role list** at login time, and the verbs they grant are r ## Verb vocabulary -Twenty-eight verbs grouped into areas: +Known verbs are grouped into areas: ### Data reads (the public catalog) @@ -25,12 +25,13 @@ Twenty-eight verbs grouped into areas: | `logs:read` | Logs tab on any layer, log detail page. | | `topology:read` | Topology tab, topology widgets on overviews. | | `profile:read` | Profiling tab (results read-only). | +| `overview:read` | Public overview dashboards. | ### Operate — dashboards, rules, diagnostics | Verb | Gates | |---|---| -| `overview:read` / `overview:write` | Overview templates admin page (`/admin/overview-templates`): list / edit. | +| `overview:write` | Overview templates admin page (`/admin/overview-templates`): edit. | | `dashboard:read` / `dashboard:write` | Layer dashboard templates admin page: list / edit. | | `alarm-setup:read` / `alarm-setup:write` | Alarm Setup page: list / edit. | | `alarm-rule:read` / `alarm-rule:write` | Alarm Rule catalog: list / edit. | @@ -48,7 +49,9 @@ Twenty-eight verbs grouped into areas: | Verb | Gates | |---|---| | `cluster:read` | Cluster Status page (`/operate/cluster`). | -| `inspect:read` | Inspect page (`/admin/inspect`). | +| `ttl:read` | Data Retention page (`/operate/ttl`). | +| `config:read` | OAP Configuration page (`/operate/config`). | +| `inspect:read` | Metrics Inspect page (`/operate/inspect`). | ### Admin surface @@ -59,7 +62,7 @@ Twenty-eight verbs grouped into areas: | `role:read` | Roles & Permissions admin page (`/admin/roles`). | | `role:write` | Reserved. | | `auth:read` | Auth Status admin page (`/admin/auth-status`) + LDAP probe. | -| `auditRead` | Reserved (audit log not yet exposed via API). | +| `audit:read` | Reserved (audit log not yet exposed via API). | ### Special @@ -90,7 +93,7 @@ Default definitions (used when `rbac.roles` is not overridden): Read-only data catalog. Deliberately limited — does not include `*:read` so a viewer cannot peek at rule definitions, live-debug sessions, setup screens, or platform internals. ``` -metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read +metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read, overview:read ``` ### `maintainer` @@ -98,7 +101,7 @@ metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read Viewer + platform monitoring. ``` -viewer baseline + cluster:read, inspect:read +viewer baseline + cluster:read, ttl:read, config:read, inspect:read ``` ### `operator` @@ -177,6 +180,7 @@ roles: - traces:read - logs:read - topology:read + - overview:read - inspect:read # so they can browse the catalog landingByRole: on-call: /alarms # land on the alarm board diff --git a/docs/components/charts.md b/docs/components/charts.md index 6403c6c..84b7fb2 100644 --- a/docs/components/charts.md +++ b/docs/components/charts.md @@ -1,145 +1,60 @@ # Charts -Horizon renders metrics through a small set of chart kinds. This page describes each kind, the inputs it accepts, and how it behaves. For the dashboard/overview widget types that select these charts, see [Dashboard Widgets](dashboard-widgets.md). +Charts are the visual forms used by dashboard and overview widgets. Most users choose a widget type rather than a chart directly; this page helps template authors understand what each chart is good for. -## Time chart +## Time Chart -**Used by:** `line` dashboard widget; ad-hoc embeds in feature pages. +Used by `line` dashboard widgets. -**Renders:** Multi-series line chart. +Best for metrics that change over time: throughput, latency, error rate, queue depth, JVM memory, CPU, and similar series. -### Props +Behavior: -| Prop | Type | Default | Notes | -|---|---|---|---| -| `series` | `Series[]` | required | One per line. | -| `height` | number | 180 | Fixed pixel height. | -| `unit` | string | — | Optional unit suffix in tooltips. | -| `accent` | string | `var(--sw-accent)` | CSS var or hex for the first series. Subsequent series cycle through the palette. | -| `format` | `int` \| `decimal` \| `compact` | — | Axis and tooltip number formatting. | +- Supports one or more lines. +- Shows a legend when there is more than one series. +- Supports a second y-axis for mixed units, such as throughput and latency. +- Shares hover position with other time charts on the same page, so operators can compare the same moment across panels. -### `Series` +Use `card` instead when the MQE expression returns a single scalar. -```ts -interface Series { - label: string; - data: Array<number | null>; - yAxisIndex?: number; // 0 = left (default), 1 = right - unit?: string; -} -``` +## Top List -### Behavior +Used by `top` dashboard widgets. -- Dual y-axis appears when any series has `yAxisIndex: 1`. -- Legend visible iff `series.length > 1`. -- Smooth lines with circle point markers. -- Tooltip is positioned so it does not clip near grid edges. -- **Synced crosshairs**: hovering broadcasts to peer time charts on the same page so they highlight the same time. -- Data-only updates animate smoothly; structure changes (series count, label set) do a full replace. +Best for ranked lists: slow endpoints, high-traffic services, worst error rates, busiest instances. -## Top list +Behavior: -**Used by:** `top` dashboard widget. +- Shows rank, name, value, and a proportional background bar. +- Supports tabs when the widget has multiple ranking expressions. +- Rows can navigate to an entity page when the result carries an entity reference. -**Renders:** Sorted list with optional tab switcher. +Use `line` instead when the expression returns a time series. -### Props +## Alarms Timeline -| Prop | Type | Default | Notes | -|---|---|---|---| -| `items` | `ReadonlyArray<DashboardTopItem>` | — | Single list mode. | -| `groups` | `ReadonlyArray<TopGroup>` | — | Multi-list mode (mutually exclusive with `items`). | -| `unit` | string | — | Widget-level unit suffix. | -| `color` | string | `var(--sw-accent)` | Bar color. | +Used on the Alarms page. -### `TopGroup` +Best for triage during an incident. It buckets firing and recovered alarms over time and lets the operator select a time range for the alarm table below. -```ts -interface TopGroup { - label: string; - expression?: string; // surfaced in tab tooltip - unit?: string; // per-tab unit override - items: DashboardTopItem[]; -} -``` +Behavior: -### `DashboardTopItem` - -```ts -interface DashboardTopItem { - name: string; - value: number | null; -} -``` - -### Layout - -- Rank column (18 px) | name (flex) | value (auto). -- Background fill bar normalized to the maximum value (per tab in multi-list mode). -- Tabs shown when `groups.length > 1`. - -## Alarms timeline - -**Used by:** Alarms page (full timeline above the alarm table). - -**Renders:** Per-minute stacked bar chart of firing + recovered alarms, with brush selection. - -### Props - -| Prop | Type | Default | Notes | -|---|---|---|---| -| `alarms` | `AlarmMessage[]` | required | Alarm messages to bucket. | -| `startTime` | number | required | Window start (ms). | -| `endTime` | number | required | Window end (ms). | -| `height` | number | 110 | Pixel height. | -| `selectedRange` | `{ startTime, endTime } \| null` | null | Current brush selection. | - -### Emits - -| Event | Payload | When | -|---|---|---| -| `select-time-range` | `{ startTime, endTime }` | Brush completed or pin flag clicked. | -| `clear-selection` | — | Empty area click or parent clears selection. | - -### Behavior - -- Two stacked series per minute bucket: firing (red), recovered (green). -- Pin flags on non-zero buckets with count labels. -- Brush (`lineX`) for range selection. Snaps to minute boundaries. -- Click on non-zero point → selects that single minute. Click on zero → clears selection. +- Shows firing and recovered alarms as stacked bars. +- Clicking a busy minute narrows the alarm list to that minute. +- Dragging a range narrows the alarm list to the selected window. ## Sparkline -**Used by:** Inline tiles, sidebar mini-charts, layer service-list picker (when a column carries a trend). - -**Renders:** Tiny inline trend line — lightweight enough to render dozens per page. - -### Props - -| Prop | Type | Default | Notes | -|---|---|---|---| -| `values` | `Array<number \| null>` | required | Data points. `null` = gap. | -| `width` | number | 56 | Internal coord width. | -| `height` | number | 14 | Internal coord height. | -| `color` | string | `var(--sw-accent)` | Line color. | -| `stroke` | number | 1.25 | Line width (px). | -| `fluid` | boolean | false | Stretch to container width. | -| `crosshairBucket` | number \| null | null | Shared hover index (for synced sparklines). | - -### Emits +Used in compact places such as tiles, sidebars, and picker rows. -| Event | Payload | When | -|---|---|---| -| `bucket-hover` | bucket index | Pointer over the chart. | -| `bucket-leave` | — | Pointer leaves the chart. | +Best for small trend hints where a full chart would be too heavy. -### Behavior +Behavior: -- Fallback single dot when fewer than 2 finite samples. -- Gap bridging on `null` entries (line breaks). -- No interactivity beyond hover broadcasting. +- Renders a tiny trend line. +- Shows a single dot when there is only one usable sample. +- Shares hover position with related sparklines when the page supports it. -## Theming +## Colors -Chart colors follow the active design theme. Per-chart accents default to the theme accent and update live when the theme is switched — no reload needed. Hex color strings are accepted for one-off cases (e.g. severity colors); prefer the theme accent for anything that should follow theming. +Charts follow the active Horizon theme. Use the layer accent or the theme accent for normal metrics, and reserve explicit colors for semantic states such as severity or error. diff --git a/docs/components/dashboard-widgets.md b/docs/components/dashboard-widgets.md index ad4b8cb..ba9f88d 100644 --- a/docs/components/dashboard-widgets.md +++ b/docs/components/dashboard-widgets.md @@ -14,29 +14,12 @@ Five widget types render on per-layer dashboards. Each `widget.type` you set in ## Common widget shape -```ts -interface DashboardWidget { - id: string; - title: string; - tip?: string; - type: 'card' | 'line' | 'top' | 'record' | 'table'; - expressions: string[]; - expressionLabels?: string[]; - expressionUnits?: string[]; - expressionAxes?: number[]; - unit?: string; - format?: 'int' | 'decimal' | 'compact'; - tableHeaders?: [string, string]; - showTableValues?: boolean; - span?: number; - rowSpan?: number; - visibleWhen?: string; - layerScope?: boolean; -} -``` - | Field | Notes | |---|---| +| `id` | Unique widget id within the dashboard. | +| `title` | Widget title shown in the card header. | +| `tip` | Optional hover hint. | +| `type` | One of `card`, `line`, `top`, `record`, or `table`. | | `expressions[]` | MQE expressions. `card` typically uses one; `line` one-per-series; `top` one-per-tab; `table` one labeled `latest(…)` metric. | | `expressionLabels[]` | Used by `top` for tab labels and by `line` for legend names. | | `expressionUnits[]` | Per-expression unit override (mixed-unit charts). | @@ -258,7 +241,7 @@ The predicate is evaluated on every data refresh; the widget disappears (rather | `top_n(...)` returning labeled list | `top` | | Record-shaped output (slow SQL, slow gRPC) | `record` | -The widget editor (planned) will warn on type / MQE mismatches. The schema does not enforce — author carefully. +The widget editor helps catch common type / MQE mismatches, but it does not replace testing against a live OAP window. After changing a widget, preview it with data before publishing. ## Per-scope widget sets diff --git a/docs/customization/adding-a-new-layer.md b/docs/customization/adding-a-new-layer.md index aa6200a..f600edc 100644 --- a/docs/customization/adding-a-new-layer.md +++ b/docs/customization/adding-a-new-layer.md @@ -94,10 +94,10 @@ Each iteration is template + BFF restart. The schema is validated at startup; a Once the template stabilizes: -- Open `/admin/layer-templates`, find the layer, click edit, save (no actual changes needed — the act of saving promotes it to admin-managed). +- Open `/admin/layer-dashboards`, find the layer, click edit, then save locally. - Subsequent edits go through the admin UI; you no longer need to rebuild and restart the BFF for cosmetic changes. -The bundled file remains in the BFF as the fallback; admin-managed copies override it. +The local bundled file remains the fallback. After you publish, the OAP-stored template becomes the runtime copy every Horizon instance reads. ### 10. Add an overview entry (optional) diff --git a/docs/customization/layer-templates.md b/docs/customization/layer-templates.md index 7d61248..3dc7ed6 100644 --- a/docs/customization/layer-templates.md +++ b/docs/customization/layer-templates.md @@ -220,29 +220,23 @@ A layer without an explicit `instance` widget set will reuse `service` widgets o ### Dashboard widget fields -```ts -interface DashboardWidget { - id: string; - title: string; - tip?: string; - type: 'card' | 'line' | 'top' | 'record'; - expressions: string[]; - expressionLabels?: string[]; // tab labels for 'top' - expressionUnits?: string[]; // per-expression unit override - expressionAxes?: number[]; // 0 = left, 1 = right (dual y-axis) - unit?: string; // widget-level unit suffix - format?: 'int' | 'decimal' | 'compact'; - span?: number; // 12-col span; default 4 - rowSpan?: number; // row count; default 1 - visibleWhen?: string; // visibility predicate - layerScope?: boolean; // evaluate against layer rather than selected service - // legacy 24-col coordinates (back-compat with old templates): - x?: number; y?: number; w?: number; h?: number; -} -``` - | Field | Notes | |---|---| +| `id` | Unique widget id within the dashboard. | +| `title` | Widget title shown in the card header. | +| `tip` | Optional hover hint. | +| `type` | Widget kind, usually `card`, `line`, `top`, `record`, or `table`. | +| `expressions[]` | MQE expressions to run. | +| `expressionLabels[]` | Tab labels for `top`, legend labels for `line`. | +| `expressionUnits[]` | Per-expression unit override. | +| `expressionAxes[]` | `0` for left axis, `1` for right axis on dual-axis line charts. | +| `unit` | Widget-level unit suffix. | +| `format` | `int`, `decimal`, or `compact`. | +| `span` | 12-column width. Default 4. | +| `rowSpan` | Row count. Default 1. | +| `visibleWhen` | Visibility predicate. | +| `layerScope` | Evaluate against the whole layer rather than the selected service. | +| `x`, `y`, `w`, `h` | Legacy coordinates kept for old templates. Prefer `span` and `rowSpan`. | | `type` | `card` for single scalar (MQE collapses to one number); `line` for time-series; `top` for sorted list; `record` for tabular records (slow SQL, slow statements). | | `expressions[]` | Array of MQE expressions. `card` typically uses one; `line` uses one per series; `top` may use multiple (each becomes a tab). | | `expressionLabels[]` | Used by `top` to label each tab. | @@ -325,9 +319,9 @@ Service-name parsing rule. Extracts a cluster (or other token) from the OAP-repo When set, the layer's service list groups by `cluster`. Without it, services are listed flat. -## Admin editor — edit locally, publish on your terms +## Admin Editor -Layer templates are editable at runtime via `/admin/layer-templates` (verb `dashboard:write`). The editor shows the JSON tree with per-field type-aware controls; changes are validated against the same schema as the bundled files. +Layer templates are editable at runtime via **Dashboard setup → Layer dashboards** (`/admin/layer-dashboards`, verb `dashboard:write`). The editor shows layer-specific controls for service, instance, endpoint, topology, trace, log, and profiling views. The save/publish model has two steps: @@ -357,7 +351,7 @@ Read the bundled JSON for the closest layer to yours before authoring a new temp ## Hot reload -Template changes (bundled or admin-edited) take effect on the next `/api/menu` or `/api/layer/:key/dashboard/config` request. Browsers see the new shape on the next page navigation. No BFF restart needed. +Template changes made in the admin editor take effect on the next menu or dashboard refresh. Bundled file changes made outside Horizon require a BFF restart. ## Common patterns diff --git a/docs/customization/menu-structure.md b/docs/customization/menu-structure.md index 9d606bf..7986ee5 100644 --- a/docs/customization/menu-structure.md +++ b/docs/customization/menu-structure.md @@ -1,150 +1,83 @@ -# Menu Structure - -The Horizon sidebar is **composed from active OAP layers**, not hand-written. There is no "edit sidebar items" page — what shows up in the sidebar is a function of: - -1. Which layers OAP currently exposes via `listLayers`. -2. The bundled per-layer JSON templates (`apps/bff/src/bundled_templates/layers/<key>.json`). -3. Per-user preferences (landing order, visibility toggles) held in the setup store. - -This page documents how those three combine into the live sidebar. - -## Data flow - -1. **OAP discovery.** Layers reported by `listLayers` are "active". -2. **Template merge.** For each active layer, the bundled `bundled_templates/layers/<key>.json` (or defaults if absent) is merged with OAP-provided data, contributing template cosmetics: `alias`, `color`, `group`, `visibility`, `caps`, `slots`, `header`, `overview`, `log`, `traces`, `naming`, `documentLink`. -3. **Counts.** Each layer carries a service count from `listServices(layer)`. The count is `-1` if OAP is unreachable. -4. **Sidebar render.** The sidebar shows the layer list, ordered per the user's landing-order preference. - -## The `MenuResponse` shape - -```ts -interface MenuResponse { - layers: LayerDef[]; - generatedAt: number; - oap: { reachable: boolean; queryUrl: string; error?: string }; -} - -interface LayerDef { - key: string; // OAP layer enum (UPPER_SNAKE) - name: string; // Display name from OAP - color: string; // Sidebar accent (hex or CSS var) - serviceCount: number; // From listServices; -1 if OAP unreachable - active: boolean; // True iff returned by listLayers - group?: string; // Sidebar grouping label - visibility?: 'public' | 'operate'; // Section placement - normal?: boolean | null; // Affects MQE scope (per OAP) - level: number | null; // From listLayerLevels (sort hint) - documentLink?: string; // External docs URL - slots: LayerSlots; // Entity term overrides - caps: LayerCaps; // Feature toggles - header?: LayerHeaderConfig; // Service-list picker columns - overview?: LayerOverviewConfig; // Overview tile config - log?: LogConfig; // Logs tab scope - traces?: { source?: 'native' | 'zipkin' | 'both' }; - naming?: ServiceNamingRule; -} -``` - -## Sidebar sections - -The sidebar has two main sections + the static Operate group: - -### Layers +# Menu and Layers -Active, public layers (`visibility: 'public'`, `serviceCount > 0`). Sorted by: +Horizon's sidebar follows the data OAP reports. You do not hand-build a menu tree in Horizon; you make OAP expose layers, then use templates and user preferences to control how those layers appear. -1. Per-user `landing.priority` from the setup store. -2. Falls back to `level` from `listLayerLevels` when no user priority is set. +## What Controls the Sidebar -A layer with `serviceCount === 0` is hidden from the Layers section but still available for the admin's setup screen ("enable this layer when services appear"). +| Source | What it controls | +|---|---| +| OAP layers | Whether a layer exists and whether it has services. | +| Layer templates | Display name, color, group, visible tabs, service-list columns, trace/log behavior, and dashboard widgets. | +| User preference | Personal ordering of visible layers on the landing page and sidebar. | +| RBAC | Whether operate, dashboard setup, and admin pages are visible for the signed-in user. | -### Operate (per-layer, optional) +The result is intentionally reactive: when OAP starts reporting data for a layer, Horizon shows it; when a user lacks a permission, Horizon hides the page link. -Layers with `visibility: 'operate'` go under the Operate group instead of Layers. Used for self-observability layers (e.g., the OAP cluster's own metrics layer). +## Main Sidebar Areas -### Operate (static) +| Area | What appears there | +|---|---| +| Overviews | Public overview dashboards, when the user has `overview:read`. | +| Alarms | The active alarm board, when the user has `alarms:read`. | +| Layers | Active public OAP layers with at least one service. | +| Platform monitoring | Cluster Status, Data Retention, and OAP Configuration. | +| Operate | Alerting rules, DSL Management, Live Debugger, Capture History, and Metrics Inspect. | +| Dashboard setup | Overview templates, Layer dashboards, Alert page setup, and Global defaults. | +| Admin | Users, Auth status, and Roles & permissions. | -These items are always present (RBAC permitting): +Only rows the current user can open are shown. -- Cluster Status (`cluster:read`) -- Inspect (`inspect:read`) -- DSL Management (`rule:read`) -- Live Debugger (`live-debug:read`) -- Alarm Setup (`alarm-setup:read`) -- Alarm Rules (`alarm-rule:read`) +## Layer Visibility -These are not layer-derived; they are first-class Horizon features. +A layer appears under **Layers** when all of these are true: -### Admin (RBAC permitting) +1. OAP reports the layer. +2. OAP reports at least one service in that layer. +3. The layer template uses public visibility. -- Auth Status, Users, Roles & Permissions (each verb-gated; see [Admin Pages](../access-control/admin-pages.md)). -- Overview Templates editor (`overview:write`). -- Layer Templates editor (`dashboard:write`). +If a layer is meant for SkyWalking self-observability rather than application observability, set its template visibility to `operate`; Horizon places it under the Operate area instead of the main Layers list. -## Per-layer composition +## First Tab for a Layer -When a user clicks a layer in the sidebar, the first enabled sub-route is picked from this priority order: +When a user clicks a layer, Horizon opens the first enabled tab in this order: -``` -service → instance → endpoint → topology → trace → logs → profiling +```text +service -> instance -> endpoint -> topology -> trace -> logs -> profiling ``` -The enablement comes from the template's `components` flags (mapped onto `caps` in the menu response): - -```json -{ - "key": "GENERAL", - "components": { - "service": true, - "instance": true, - "endpoint": true, - "topology": true, - "trace": true, - "logs": false, - "profiling": true - } -} -``` - -A layer with `components.service: false` and only `topology: true` will land directly on the Topology tab when clicked. +Disable unsupported tabs in the layer template. For example, a layer without traces should turn the trace tab off so users do not land on an empty page. -## Customization surface +## Common Changes -| Want to | Edit | +| Goal | Where to change it | |---|---| -| Rename a layer in the sidebar | `alias` in `bundled_templates/layers/<key>.json` | -| Change a layer's color | `color` | -| Group several layers under one collapsible header | `group` (same string on multiple layers) | -| Move a layer into the Operate section | `visibility: operate` | -| Hide a tab on a layer | flip the corresponding `components.*` flag | -| Change which sub-route is the landing tab | reorder via `components` flags (the leftmost enabled wins, per priority above) | -| Add an external doc link | `documentLink` | -| Re-order layers in the sidebar | per-user via the landing-order control (setup store) | -| Add a brand-new layer | OAP-side first (must show up in `listLayers`), then add a template — see [Adding a New Layer](adding-a-new-layer.md) | - -The menu is **never user-editable as a tree** in the UI. Customization is always via: +| Rename a layer | Layer template `alias`. | +| Change a layer color | Layer template `color`. | +| Group related layers | Same layer template `group` value on each layer. | +| Move a layer to Operate | Layer template `visibility: operate`. | +| Hide a tab | Layer template `components`. | +| Change layer order | User layer-order preference. | +| Add a new layer | Add it in OAP first, then add a Horizon layer template. | -- Templates (for cosmetics + feature toggles), or -- The setup store (for per-user ordering), or -- OAP itself (for layer existence). +Use **Dashboard setup → Layer dashboards** for normal template edits. Save locally to preview, then sync to OAP when you want the change published for everyone. -## What "active" means +## When OAP Is Unreachable -A layer is `active: true` when OAP returns it from `listLayers`. An inactive layer can still appear in the menu response (so the admin can enable it via the setup page) but is **not shown in the sidebar**. Once OAP starts reporting it (e.g., once data arrives for that layer), the sidebar shows it on the next `/api/menu` refresh. +If OAP is unreachable, Horizon keeps the last known sidebar shape in memory and shows an OAP-unreachable banner. Service counts may show as unknown until OAP is reachable again. -This means: **stand up your OAP receivers first, install/configure them to ingest data for the layer you want, then refresh Horizon**. The sidebar is purely reactive to OAP state. +This avoids the worst failure mode during a short OAP outage: an empty sidebar that makes operators think configuration disappeared. -## When OAP is unreachable +## Troubleshooting -`/api/menu` returns `oap.reachable: false` and `serviceCount: -1` for every layer. The sidebar still renders the last-known shape (the BFF caches the most recent successful response in memory) with an "OAP unreachable" banner. This avoids the UX collapse of a fully empty sidebar during a brief OAP blip. - -## Polling cadence - -- The UI fetches `/api/menu` on mount and on tab focus (return-to-tab triggers a refresh). -- The BFF does not cache `/api/menu` responses cross-request — every call re-queries OAP. For very large layer counts this can be tuned; file an issue if you see latency. +| Symptom | Check | +|---|---| +| Layer missing | Confirm OAP reports the layer and at least one service. | +| Layer appears in Operate, not Layers | Check template visibility. | +| Expected tab missing | Check the layer template components. | +| User cannot see an admin page | Check their role grants in Roles & permissions. | ## Related -- [Layer Dashboard Templates](layer-templates.md) — the JSON shape that backs each layer. -- [Overview Templates](overview-templates.md) — the war-room overviews (separate from the sidebar). -- [Adding a New Layer](adding-a-new-layer.md) — end-to-end recipe. +- [Layer Dashboard Templates](layer-templates.md) +- [Overview Templates](overview-templates.md) +- [Add a Layer](adding-a-new-layer.md) diff --git a/docs/customization/overview-templates.md b/docs/customization/overview-templates.md index 1fdadd5..e3c4fb3 100644 --- a/docs/customization/overview-templates.md +++ b/docs/customization/overview-templates.md @@ -70,51 +70,23 @@ The 72 px row height is tuned for KPI tile content; widgets that need more verti ## Widget shape (common fields) -```ts -interface OverviewWidget { - id: string; - title: string; - tip?: string; - layer?: string; - type: 'metric' | 'topology' | 'section-break' | 'kpi-tile' | 'alarms' | 'metric-composite'; - span?: number; // 1–12 - rowSpan?: number; // 1–8 - // type-specific fields below - mqe?: string; // metric - unit?: string; // metric - aggregation?: 'sum' | 'avg'; // metric - cols?: number; // section-break - kpis?: OverviewKpi[]; // kpi-tile, metric-composite - showCount?: boolean; // kpi-tile - limit?: number; // alarms -} -``` - | Field | Notes | |---|---| | `id` | Unique within the dashboard. | | `title` | Card title (not used by `section-break` — uses `title` as the section header). | | `tip` | Optional one-line hover hint next to the title. | | `layer` | Layer key (UPPER_SNAKE). Used to scope MQE evaluation. Optional for `section-break` and `alarms` (alarms can scope server-side if the layer is set). | +| `type` | One of `metric`, `topology`, `section-break`, `kpi-tile`, `alarms`, or `metric-composite`. | | `span` | Column span. Defaults vary per widget type. | | `rowSpan` | Row span. Defaults vary per widget type. | +| `mqe`, `unit`, `aggregation` | Metric-specific fields. | +| `cols` | Section-break column count for following widgets. | +| `kpis`, `showCount`, `limit` | Type-specific fields described below. | ## `OverviewKpi` Used by `kpi-tile` and `metric-composite`: -```ts -interface OverviewKpi { - label: string; - mqe?: string; - unit?: string; - aggregation?: 'sum' | 'avg'; - style?: 'number' | 'progress-bar'; - max?: number; - source?: 'mqe' | 'service-count'; -} -``` - | Field | Notes | |---|---| | `label` | Row label. | @@ -232,9 +204,9 @@ Following widgets render in a **6-column** grid (rather than 12) until the next Read-only — Horizon does not support acknowledge / close / silence operations. Alarm recovery is backend-automatic. -## Admin editor +## Admin Editor -Overview templates are editable at runtime via `/admin/overview-templates` (verb `overview:write`). The editor: +Overview templates are editable at runtime via **Dashboard setup → Overview templates** (`/admin/overview-templates`, verb `overview:write`). The editor: - Lists all bundled overviews + any added ones, with widget count and editable flag. - For each overview, shows the widget array with per-widget controls. @@ -252,22 +224,16 @@ Overview templates are editable at runtime via `/admin/overview-templates` (verb - **Add / remove widgets** with the type picker. - **Preview** renders the in-progress template against live OAP data. -Changes go through `POST /api/admin/overview-templates/:id`, validated server-side before being written. +The save/publish model has two steps: -## HTTP API - -| Method | Path | Verb | Notes | -|---|---|---|---| -| GET | `/api/admin/overview-templates` | `overview:read` | List all overviews. | -| GET | `/api/admin/overview-templates/:id` | `overview:read` | Full config. | -| POST | `/api/admin/overview-templates/:id` | `overview:write` | Replace config. Validated, cache invalidated on write. | -| DELETE | `/api/admin/overview-templates/:id` | `overview:write` | Remove overview. | +1. **Save locally.** The edit is written to the local bundled copy and renders immediately for preview. OAP is not changed yet. +2. **Publish.** **Sync all to OAP** pushes diverged overview templates to OAP behind a confirmation that lists the affected templates. -The view route `/overview/:id` calls `GET /api/overview/:id/data` (verb `metrics:read`) which evaluates the widgets server-side and returns the resolved value set. +If the local copy differs from OAP, Horizon shows the template as **diverged**. Use **Show diff** to compare local and remote, **Keep my local edits** to preview, or **Use live** to discard the local copy and render the OAP version. ## Hot reload -Bundled file changes require a BFF restart (templates are loaded at startup). Admin-API edits go through the cache and apply on the next data fetch — no restart needed. +Admin editor changes apply on the next overview refresh. Bundled file changes made outside Horizon require a BFF restart. ## Common patterns diff --git a/docs/design-target.md b/docs/design-target.md index 48be514..49fbf83 100644 --- a/docs/design-target.md +++ b/docs/design-target.md @@ -48,7 +48,7 @@ The per-layer drill-down presents a single service through every data type SkyWa | Logs | log records | per-layer scope (service / instance / endpoint) | | Profiling | trace / eBPF / async profiler | scope-aware widget set | -The renderer is template-driven (see [Customization → Layer Dashboard Templates](customization/layer-templates.md)). New layers do not require new Vue files; they require a new JSON template. +The renderer is template-driven (see [Customization → Layer Dashboard Templates](customization/layer-templates.md)). New layers require a JSON template, not a custom UI build. ### Customization is the whole key @@ -61,7 +61,7 @@ Every visual decision a site operator wants to make is template-driven: - **Overview content** — overview template JSON; type-aware admin editor edits each widget's only-relevant fields. - **Authentication / authorization** — `horizon.yaml` + `/admin/auth-status` page. -There is no "add a custom Vue component" extension point — adding rendering primitives is a code change. Adding **content** is always configuration. +There is no custom UI plugin extension point. Adding a new rendering primitive requires a Horizon release; adding **content** is configuration. ### Density beats whitespace diff --git a/docs/menu.yml b/docs/menu.yml index f21d5df..9cef5dc 100644 --- a/docs/menu.yml +++ b/docs/menu.yml @@ -14,57 +14,65 @@ # limitations under the License. catalog: - - name: "Horizon UI Overview" + - name: "Overview" path: "/readme" - - name: "Design Target" - path: "/design-target" - - - name: "Compatibility" - catalog: - - name: "OAP Version" - path: "/compatibility/oap-version" - - name: "Required OAP Modules" - path: "/compatibility/required-modules" - - name: "Network Ports" - path: "/compatibility/ports" - - name: "Cluster Status Check Sequence" - path: "/compatibility/cluster-status" - - name: "Setup" catalog: - name: "Quick Start" path: "/setup/overview" - name: "Container Image" path: "/setup/container-image" - - name: "horizon.yaml Reference" + - name: "Configuration File" path: "/setup/horizon-yaml" - - name: "server" + - name: "Server Listener" path: "/setup/server" - - name: "oap" + - name: "OAP Connection" path: "/setup/oap" - - name: "auth" + - name: "Authentication" path: "/setup/auth" - - name: "rbac" + - name: "Access Control" path: "/setup/rbac" - - name: "session" + - name: "Sessions" path: "/setup/session" - - name: "audit" + - name: "Audit Log File" path: "/setup/audit" - - name: "setup / alarms files" + - name: "Runtime State Files" path: "/setup/files" - - name: "debugLog" + - name: "Wire Debug Log" path: "/setup/debug-log" + - name: "Compatibility" + catalog: + - name: "OAP Version" + path: "/compatibility/oap-version" + - name: "Network Ports" + path: "/compatibility/ports" + - name: "Required OAP Modules" + path: "/compatibility/required-modules" + - name: "Cluster Status Checks" + path: "/compatibility/cluster-status" + + - name: "Operate" + catalog: + - name: "Cluster Status" + path: "/operate/cluster-metadata" + - name: "Data Retention" + path: "/operate/data-retention" + - name: "OAP Configuration" + path: "/operate/oap-configuration" + - name: "Metrics Inspect" + path: "/operate/inspect" + - name: "Access Control" catalog: - - name: "Local Backend" + - name: "Local Users" path: "/access-control/local-backend" - - name: "LDAP Backend" + - name: "LDAP Login" path: "/access-control/ldap-backend" - name: "Break-Glass Access" path: "/access-control/break-glass" - - name: "RBAC: Roles & Verbs" + - name: "Roles and Permissions" path: "/access-control/rbac" - name: "Audit Log" path: "/access-control/audit-log" @@ -73,27 +81,20 @@ catalog: - name: "Customization" catalog: - - name: "Menu Structure" + - name: "Menu and Layers" path: "/customization/menu-structure" - name: "Layer Dashboard Templates" path: "/customization/layer-templates" - name: "Overview Templates" path: "/customization/overview-templates" - - name: "Adding a New Layer" + - name: "Add a Layer" path: "/customization/adding-a-new-layer" - - name: "Components" + - name: "Reference" catalog: + - name: "Design Target" + path: "/design-target" - name: "Overview Widgets" path: "/components/overview-widgets" - name: "Dashboard Widgets" path: "/components/dashboard-widgets" - - name: "Charts" - path: "/components/charts" - - - name: "Operate" - catalog: - - name: "Cluster Status & Metadata" - path: "/operate/cluster-metadata" - - name: "Inspect" - path: "/operate/inspect" diff --git a/docs/operate/cluster-metadata.md b/docs/operate/cluster-metadata.md index edffd08..4cf0a66 100644 --- a/docs/operate/cluster-metadata.md +++ b/docs/operate/cluster-metadata.md @@ -62,18 +62,6 @@ This is **informational only**. A 3-node OAP cluster behind one DNS name should The cluster-members section is **not** required for Horizon to function; it is a sanity check that the operator's expectation matches reality. -## Coming soon strip - -The page documents upcoming additions inline. These are not implemented today; the strip is there so operators know what's on the roadmap and what is and isn't currently surfaced: - -- **Per-node module activity matrix** — module × provider × node grid. Requires per-node admin calls (currently the dump is consumed cluster-wide). -- **Storage backend health** — BanyanDB / Elasticsearch / JDBC: connection pool, index lag, throughput. -- **Receiver activity** — gRPC / HTTP / Kafka / OTLP: throughput, queue depth. -- **Effective-configuration tree** — two-node diff of merged config (advanced troubleshooting). -- **TTL & retention grid** — hot / warm / cold storage timeline per metric scope. - -When these land, this page is where they will surface; the data flow will follow the same pattern as today's panes (BFF preflight call → cached → polled). - ## Reading the page during an incident 1. **Both panes green?** Backend is fine; the problem is elsewhere (network from browser, BFF process, OAP-side data ingestion). diff --git a/docs/operate/data-retention.md b/docs/operate/data-retention.md new file mode 100644 index 0000000..563bc85 --- /dev/null +++ b/docs/operate/data-retention.md @@ -0,0 +1,28 @@ +# Data Retention + +Path: `/operate/ttl`. Verb: `ttl:read` (granted by maintainer, operator, admin). + +The Data Retention page shows how long the connected OAP keeps records and metrics. It is read-only; change retention in OAP configuration, then refresh Horizon. + +## What You See + +The page has two sections: + +| Section | What it means | +|---|---| +| Records | Event-style data such as traces, Zipkin traces, logs, and browser error logs. | +| Metrics | Aggregated metric tiers: minute, hour, day, and metadata when the OAP backend exposes it. | + +Values are shown in days. A cold value means BanyanDB cold-stage retention. `no cold stage` means the connected OAP has no cold storage stage for that data class. + +## Requirements + +- OAP query port reachable from Horizon. +- The logged-in user has `ttl:read`. +- OAP supports `getRecordsTTL` and `getMetricsTTL`. + +If the page reports OAP unreachable, check `oap.queryUrl` and the network path to the query port. + +## During Operations + +Use this page before changing dashboard time windows, alert retention, or storage sizing. If a user expects old traces or metrics and Horizon cannot find them, compare the requested time range with this page first. diff --git a/docs/operate/inspect.md b/docs/operate/inspect.md index 0f843f1..5c9dd4d 100644 --- a/docs/operate/inspect.md +++ b/docs/operate/inspect.md @@ -1,6 +1,6 @@ # Inspect -Path: `/admin/inspect`. Verb: `inspect:read` (granted by maintainer, operator, admin). +Path: `/operate/inspect`. Verb: `inspect:read` (granted by maintainer, operator, admin). The Inspect page lets the operator browse OAP's live metric catalog and enumerate the entities (services, instances, endpoints, processes, …) that have data for a given metric. It is built on OAP's **Inspect API**, which is **v11-only** — the page does not render on v10. diff --git a/docs/operate/oap-configuration.md b/docs/operate/oap-configuration.md new file mode 100644 index 0000000..6919d5f --- /dev/null +++ b/docs/operate/oap-configuration.md @@ -0,0 +1,24 @@ +# OAP Configuration + +Path: `/operate/config`. Verb: `config:read` (granted by maintainer, operator, admin). + +The OAP Configuration page shows the connected OAP's resolved runtime configuration. It is read-only and intended for support and incident triage. + +## What You See + +Horizon reads OAP's admin-port config dump and groups keys by module. Use the filter box to find a module, selector, or value. + +Secret values are masked by OAP before Horizon displays them. Masked values appear as `******`. + +## Requirements + +- OAP 11.x. +- `SW_ADMIN_SERVER=default` on OAP. +- The OAP admin port, usually `17128`, reachable from Horizon. +- The logged-in user has `config:read`. + +If the page reports the admin host is unreachable, check the OAP admin-server module and the Service, firewall, or load balancer exposing the admin port. + +## During Operations + +Use this page to confirm what OAP actually started with, especially after a config change, deployment rollback, or module enablement change. For module health, start with [Cluster Status](cluster-metadata.md); for the complete key/value view, use this page. diff --git a/docs/setup/audit.md b/docs/setup/audit.md index f927621..1097bdd 100644 --- a/docs/setup/audit.md +++ b/docs/setup/audit.md @@ -1,4 +1,4 @@ -# audit +# Audit Log File Audit log file path. The format and event schema are documented in [Access Control → Audit Log](../access-control/audit-log.md); this page is the `horizon.yaml` shape. diff --git a/docs/setup/auth.md b/docs/setup/auth.md index f21a3aa..eefb7e9 100644 --- a/docs/setup/auth.md +++ b/docs/setup/auth.md @@ -1,4 +1,4 @@ -# auth +# Authentication Authentication backend selection. Detailed per-backend configuration lives under [Access Control](../access-control/local-backend.md); this page is the `horizon.yaml` shape. diff --git a/docs/setup/debug-log.md b/docs/setup/debug-log.md index bd52578..376d83f 100644 --- a/docs/setup/debug-log.md +++ b/docs/setup/debug-log.md @@ -1,4 +1,4 @@ -# debugLog +# Wire Debug Log Wire-level HTTP request/response log for troubleshooting OAP communication. **Off by default.** Very verbose — only use when actively debugging. diff --git a/docs/setup/files.md b/docs/setup/files.md index b6374fa..cb98dcc 100644 --- a/docs/setup/files.md +++ b/docs/setup/files.md @@ -1,4 +1,4 @@ -# setup and alarms +# Runtime State Files State files for user-configured settings. Both write JSON, both are managed by the BFF, neither needs hand-editing. diff --git a/docs/setup/oap.md b/docs/setup/oap.md index c12c500..9fe789e 100644 --- a/docs/setup/oap.md +++ b/docs/setup/oap.md @@ -1,4 +1,4 @@ -# oap +# OAP Connection Connectivity to the upstream Apache SkyWalking OAP cluster. Required for everything except the login page. diff --git a/docs/setup/overview.md b/docs/setup/overview.md index 0b2a1ab..9abdae4 100644 --- a/docs/setup/overview.md +++ b/docs/setup/overview.md @@ -1,18 +1,26 @@ # Setup Quick Start -This page is the smallest possible path from "no Horizon" to "Horizon in front of a running OAP". For per-section field reference, see the rest of the **Setup** chapter. For a containerized deployment, see [Container Image](container-image.md) instead — it covers image tags, env vars, volume mounts, and a Kubernetes example. +This page is the shortest path from "no Horizon" to "Horizon in front of a running OAP". It uses the released binary layout first. For containerized deployments, use [Container Image](container-image.md). ## Prerequisites - Apache SkyWalking **OAP 11.x** (native). OAP 10.x runs the data-plane stack (dashboards, traces, logs, topology, alarms, profiling) but the entire admin port — Inspect, DSL Management, Live Debugger, Alarm Rule editor, Cluster Status → Admin pane, and OAP UI-template sync — is v11-only. See [Compatibility → OAP Version](../compatibility/oap-version.md) for the feature-vs-version matrix. - Network reachability from the Horizon BFF to the OAP query port (`:12800`) and admin port (`:17128`). See [Network Ports](../compatibility/ports.md). -- Node.js 20+, pnpm 10+ (for source builds; pinned via Corepack). A pre-built artifact only needs Node.js. +- Node.js 20+ for the binary tarball. Source builds also need pnpm 10+. ## Five-step start -### 1. Place `horizon.yaml` next to the BFF +### 1. Unpack Horizon -Copy `horizon.example.yaml` (in the repo root) to `horizon.yaml` in your working directory. The BFF looks for `./horizon.yaml` by default; override with `HORIZON_CONFIG=/path/to/file`. +Unpack the binary tarball and copy the example config: + +```sh +tar -xzf apache-skywalking-horizon-ui-0.5.0-bin.tar.gz +cd apache-skywalking-horizon-ui-0.5.0-bin +cp horizon.example.yaml horizon.yaml +``` + +The binary is self-contained: `server.js`, `node_modules/`, `static/`, and bundled templates are already present. There is no `pnpm install` step. ### 2. Point Horizon at OAP @@ -36,11 +44,10 @@ oap: ### 3. Add at least one local user -With no users configured, the BFF boots so the login page can show the setup-required state, but no login can succeed. Generate an argon2 hash: +With no users configured, Horizon starts but no login can succeed. Generate an Argon2id hash with the source checkout helper or any Argon2id-capable password tool: ```sh pnpm --filter bff cli:hash -# prompts for the password, prints the hash ``` Paste the hash into `auth.local.users`: @@ -59,13 +66,13 @@ For LDAP setup instead, see [Access Control → LDAP Backend](../access-control/ ### 4. Start the BFF +From inside the unpacked binary directory: + ```sh -pnpm --filter bff dev -# or, for a built artifact: -node apps/bff/dist/server.js +HORIZON_CONFIG=./horizon.yaml HORIZON_STATIC_DIR=./static node server.js ``` -The BFF defaults to `127.0.0.1:8081`. For production, bind to `0.0.0.0` and put TLS termination in front: +Horizon defaults to `127.0.0.1:8081`. For production, bind to `0.0.0.0` and put TLS termination in front: ```yaml server: @@ -84,6 +91,30 @@ Browse to `http://<bff-host>:8081/`. Log in with the user you created. The first If either pane is red or yellow, see [Cluster Status Check Sequence](../compatibility/cluster-status.md) for triage. +## Container start + +For Docker or Kubernetes, mount the same `horizon.yaml` and `/data` state volume: + +```sh +docker run -d --name horizon \ + -p 8081:8081 \ + -v "$PWD/horizon.yaml:/app/horizon.yaml:ro" \ + -v horizon-state:/data \ + ghcr.io/apache/skywalking-horizon-ui:0.5.0 +``` + +See [Container Image](container-image.md) for image tags, Kubernetes YAML, log handling, and probes. + +## Source build + +Use source builds when you are developing Horizon itself: + +```sh +pnpm install +pnpm package +HORIZON_CONFIG=./horizon.yaml HORIZON_STATIC_DIR=./dist/static node dist/server.js +``` + ## Production checklist - [ ] `server.host: 0.0.0.0` and TLS terminator in front. diff --git a/docs/setup/rbac.md b/docs/setup/rbac.md index 8ea0423..963e83b 100644 --- a/docs/setup/rbac.md +++ b/docs/setup/rbac.md @@ -1,4 +1,4 @@ -# rbac +# Access Control Configuration Role-Based Access Control. Defines the role → verb grants and the post-login landing route per role. Full behavior reference (verb vocabulary, grant matching, where each verb gates) is in [Access Control → RBAC: Roles & Verbs](../access-control/rbac.md); this page is the `horizon.yaml` shape. @@ -8,8 +8,8 @@ Role-Based Access Control. Defines the role → verb grants and the post-login l rbac: enabled: true roles: - viewer: [metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read] - maintainer: [metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read, cluster:read, inspect:read] + viewer: [metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read, overview:read] + maintainer: [metrics:read, alarms:read, traces:read, logs:read, topology:read, profile:read, overview:read, cluster:read, ttl:read, config:read, inspect:read] operator: [metrics:read, ..., rule:*, live-debug:*, profile:enable] admin: ["*"] landingByRole: @@ -31,9 +31,9 @@ rbac: | Role | Purpose | Grants | |---|---|---| -| `viewer` | Read-only data catalog. | `metrics:read`, `alarms:read`, `traces:read`, `logs:read`, `topology:read`, `profile:read`. Deliberately not `*:read` so the viewer cannot see rule definitions, live-debug sessions, setup screens, or platform internals. | -| `maintainer` | Viewer + platform monitoring. | viewer baseline + `cluster:read`, `inspect:read`. | -| `operator` | Configures observability. | maintainer baseline + `overview:read/write`, `setup:read/write`, `dashboard:read/write`, `alarm-setup:read/write`, `alarm-rule:read/write`, `rule:*` (including `rule:write:structural`, `rule:delete`, `rule:debug`), `live-debug:*`, `profile:enable`. | +| `viewer` | Read-only data catalog and public overviews. | `metrics:read`, `alarms:read`, `traces:read`, `logs:read`, `topology:read`, `profile:read`, `overview:read`. Deliberately not `*:read` so the viewer cannot see rule definitions, live-debug sessions, setup screens, or platform internals. | +| `maintainer` | Viewer + platform monitoring. | viewer baseline + `cluster:read`, `ttl:read`, `config:read`, `inspect:read`. | +| `operator` | Configures observability. | maintainer baseline + `overview:write`, `setup:read/write`, `dashboard:read/write`, `alarm-setup:read/write`, `alarm-rule:read/write`, `rule:*` (including `rule:write:structural`, `rule:delete`, `rule:debug`), `live-debug:*`, `profile:enable`. | | `admin` | Unrestricted. | `*`. | ## Verb grammar @@ -88,6 +88,7 @@ rbac: - traces:read - logs:read - topology:read + - overview:read - inspect:read # so they can poke at the catalog - live-debug:read # but not write landingByRole: diff --git a/docs/setup/server.md b/docs/setup/server.md index 5023aa6..dbc271d 100644 --- a/docs/setup/server.md +++ b/docs/setup/server.md @@ -1,4 +1,4 @@ -# server +# Server Listener HTTP listener for the Horizon BFF. Also serves the built UI as static assets when `staticDir` is set. diff --git a/docs/setup/session.md b/docs/setup/session.md index 34cd1c8..74064f6 100644 --- a/docs/setup/session.md +++ b/docs/setup/session.md @@ -1,4 +1,4 @@ -# session +# Sessions HTTP session cookie configuration. diff --git a/horizon.example.yaml b/horizon.example.yaml index 224e90e..8accd30 100644 --- a/horizon.example.yaml +++ b/horizon.example.yaml @@ -144,6 +144,8 @@ rbac: - profile:read - overview:read - cluster:read + - ttl:read + - config:read - inspect:read # Configures observability: dashboards, alarm rules, DSL/OAL, @@ -157,6 +159,8 @@ rbac: - topology:read - profile:read - cluster:read + - ttl:read + - config:read - inspect:read - overview:read - overview:write
