Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
{
Expand Down
2 changes: 1 addition & 1 deletion plugins/tsuga/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
3 changes: 2 additions & 1 deletion plugins/tsuga/skills/tsuga-build-dashboard/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (<filter>)` 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 (<filter>)`, 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": {
Expand Down Expand Up @@ -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 <name>` 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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion plugins/tsuga/skills/tsuga-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:<B`.
- Bare tokens search log message text. `message:X` matches the entire exact message; use `message:*token*` only for a single-token substring.
Expand Down
Loading