From c39989ef6f092739ed2c41a5fb4296fc41281caf Mon Sep 17 00:00:00 2001 From: Arthur Verrez Date: Wed, 24 Jun 2026 15:07:58 +0200 Subject: [PATCH 1/2] docs(tsuga-build-dashboard): percent needs *100, always alias series --- .claude-plugin/marketplace.json | 2 +- plugins/tsuga/.claude-plugin/plugin.json | 2 +- plugins/tsuga/skills/tsuga-build-dashboard/SKILL.md | 3 ++- .../tsuga-build-dashboard/references/widget-reference.md | 8 ++++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 59a92f7..3c934ac 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,7 +6,7 @@ }, "metadata": { "description": "Tsuga toolkit for AI coding agents: one plugin with the tsuga CLI driver, live-platform investigation, dashboards, incident workflows, OpenTelemetry instrumentation, Collector, signal-choice, telemetry debug, and audit skills.", - "version": "0.8.3" + "version": "0.8.4" }, "plugins": [ { diff --git a/plugins/tsuga/.claude-plugin/plugin.json b/plugins/tsuga/.claude-plugin/plugin.json index 3539002..3c07eea 100644 --- a/plugins/tsuga/.claude-plugin/plugin.json +++ b/plugins/tsuga/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "tsuga", "description": "Tsuga observability plugin: the `tsuga` CLI driver (commands, TQL syntax, aggregation bodies, counter math, deep links, cloud/k8s translators); live-platform investigation for service health, errors, latency, and monitor coverage; dashboard building; incident orchestration; OpenTelemetry SDK, Collector, OTTL, signal-choice, telemetry debug, and audit skills; and meta-skills for building and validating skill bundles.", - "version": "0.8.3", + "version": "0.8.4", "author": { "name": "Tsuga Engineering", "email": "engineering@tsuga.com" diff --git a/plugins/tsuga/skills/tsuga-build-dashboard/SKILL.md b/plugins/tsuga/skills/tsuga-build-dashboard/SKILL.md index 15791c6..95eb5dd 100644 --- a/plugins/tsuga/skills/tsuga-build-dashboard/SKILL.md +++ b/plugins/tsuga/skills/tsuga-build-dashboard/SKILL.md @@ -79,7 +79,8 @@ Key structural rules: - `owner` must be a team ID — resolve with `tsuga teams list` - Each graph requires a unique `id`, a `visualization` object, and a `layout` object - `query-value` does not support `groupBy` — the API silently drops it -- Name each series in the legend via `visualization.aliases.queries`, keyed by the query's zero-based index as a string (`"0"`, `"1"`, ...) — NOT `formula`'s `"q1"`/`"q2"`; wrong keys are silently ignored (see `references/widget-reference.md`) +- Always name each series in the legend via `visualization.aliases.queries`, keyed by the query's zero-based index as a string (`"0"`, `"1"`, ...), NOT `formula`'s `"q1"`/`"q2"`; wrong keys are silently ignored (see `references/widget-reference.md`) +- A `percent` normalizer only appends `%`; it does not multiply by 100. Scale in the `formula` (`q1/q2*100`) and put `query-value` `conditions` thresholds on the resulting 0-100 scale (see `references/widget-reference.md`) - List-style widgets take a single `query` string. Variants: `list` (logs matching a Tsuga query), `list-log-patterns` (logs clustered into patterns), `list-connection` (datastore rows via `connectionId` + read-only SQL) - Include dashboard-level env + team filters when they are relevant to the dashboard audience: diff --git a/plugins/tsuga/skills/tsuga-build-dashboard/references/widget-reference.md b/plugins/tsuga/skills/tsuga-build-dashboard/references/widget-reference.md index bca494c..760770a 100644 --- a/plugins/tsuga/skills/tsuga-build-dashboard/references/widget-reference.md +++ b/plugins/tsuga/skills/tsuga-build-dashboard/references/widget-reference.md @@ -27,7 +27,7 @@ Max 15 queries per widget. `formula` references queries by position: `"q1"` = fi ### Series names in the legend (`aliases`) -Every series renders with an auto-generated label like `Count on ()` unless you name it. To set legible legend names, add `aliases` to the visualization: +**Always set `aliases` on any widget with more than one query/series or a `formula`.** Otherwise every series renders as `Count on ()`, which is unreadable when two series share a filter prefix (for example, two `http.headers.x-tsuga-source:mcp-server AND ...` counts both show as the same truncated `Count on (http.headers.x-tsuga-...)`). To set legible legend names, add `aliases` to the visualization: ```json "aliases": { @@ -496,11 +496,13 @@ Every numeric widget should have a `normalizer` so values display with meaningfu |------|------|---------| | Duration | `{"type": "duration", "unit": "ms"}` | Latency — set `unit` to the metric's actual unit (ns, us, ms, s, m, h, days) | | Data | `{"type": "data", "unit": "B"}` | Bytes — set `unit` to the value's actual unit; OTel byte metrics are bytes → `B` (B, KB, MB, GB, TB, PB) | -| Percent | `{"type": "percent"}` | Ratios, utilization | +| Percent | `{"type": "percent"}` | Percentages (appends `%` to the value as-is; does NOT multiply by 100, see note) | | Custom | `{"type": "custom", "unit": "req/s"}` | Everything else — provide a unit label | **Critical — for `data` and `duration`, `unit` is the unit the raw value is ALREADY in, not a display target.** The UI auto-scales *up* from that base unit and picks the readable magnitude itself, so set it to the metric's true unit and let the widget format. OTel byte metrics (`*_bytes`, `intake_api_batch_bytes`, `quickwit_*_bytes`, …) emit **bytes** → use `"B"`, and the widget renders `58 TB`, `4.2 GB`, etc. on its own. Setting a larger base like `"GB"` on a bytes value overstates the reading by 1e9 — e.g. 58 TB displays as "58M PB". Always confirm the metric's unit with `tsuga metrics get ` before choosing. +**Critical: `percent` does NOT multiply by 100.** It only appends a `%` sign to the value as-is, so a raw ratio of `0.12` renders as `0.12%`, not `12%`. Always scale to a 0-100 number in the `formula` (`q1/q2*100`), so `0.12` becomes `12` and displays as `12%`. Consequence: `query-value` `conditions` (and `gauge` / `bar` thresholds) compare the post-`*100` value, so set them on the 0-100 scale: `5` and `20` for 5% / 20%, not `0.05` / `0.2`. + --- ## Formula Patterns @@ -513,6 +515,8 @@ Formulas reference queries by position. Place the formula at body level (same le | Utilization % | `(q1 / q2) * 100` | `{"type": "percent"}` | | Gap / delta | `q1 - q2` | Match the unit of q1 and q2 | +The `*100` in the percentage rows is mandatory: the `percent` normalizer appends `%` without scaling (see Normalizer Reference). Keep any matching `conditions` thresholds on the same 0-100 scale. + --- ## Functions From f7e78ab943abc8da0aaa6b8100cf8e2512cb1e05 Mon Sep 17 00:00:00 2001 From: Arthur Verrez Date: Wed, 24 Jun 2026 15:20:52 +0200 Subject: [PATCH 2/2] docs(tsuga-cli): field-level OR field:(a OR b) now works --- plugins/tsuga/skills/tsuga-cli/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tsuga/skills/tsuga-cli/SKILL.md b/plugins/tsuga/skills/tsuga-cli/SKILL.md index babd368..3e74e28 100644 --- a/plugins/tsuga/skills/tsuga-cli/SKILL.md +++ b/plugins/tsuga/skills/tsuga-cli/SKILL.md @@ -58,7 +58,7 @@ If docs are unavailable, report the CLI error and use `--help` / `--generate-ske These fail silently or are easy to misread: - AND is the default. `OR` and `NOT` must be uppercase. -- No field-distributed OR: `field:(a OR b)` matches nothing. Use `(field:a OR field:b)`. +- Field-level OR is supported: `field:(a OR b)` matches any listed value (same as `(field:a OR field:b)`). - No `_exists_:field`. Use `field:*`. - Inclusive ranges use `field:[A TO B]`. Exclusive `{A TO B}` is rejected; emulate with `field:>A field: