Dashboard Agent: investigations, watches, alerts, and notifications - #4418
Dashboard Agent: investigations, watches, alerts, and notifications#4418kathiekiwi wants to merge 158 commits into
Conversation
…signals Gauges are read inside the enqueue/dequeue Lua and returned on the script reply as a 2-tuple; counters are cumulative odometers. The run-queue Redis carries no metrics stream of its own.
…counters entryOrderKey returns a string built with BigInt math so ordering stays correct at real epoch magnitudes. Odometer keys are namespaced by definition name. The consumer reports null lag for a missing consumer group instead of 0, and empty gauge values parse as NaN rather than 0.
…ng order keys The wait-time quantile materialized view now excludes wait_ms = 0 rows so it matches the count aggregation. order_key accepts a string or a number. Migration comments no longer contain semicolons that split the migration into invalid statements.
…rride The queues list tolerates a metrics query failure by rendering without metrics and logging a warning. UsageSparkline renders its total override even when every bucket is zero. The queue detail page returns 404 and its loader skips the metrics query when the feature flag is off. The seed script validates bucket size and only writes ClickHouse against a local host.
A bucket-led ORDER BY DESC combined with fillGaps emitted an ascending WITH FILL (positive step, ascending bounds), which produces invalid or empty fills. Skip the gap-fill rewrite for descending orders and let the plain descending query stand. Adds a DESC fillGaps test.
Packs the stream sequence with a 1e6 factor (was 1e5) so up to 1M entries per millisecond per shard fit before a seq could spill into the next millisecond's range, far above what a single Redis stream can produce. ms*1e6 stays within UInt64. Also fixes the webapp mapping test that still expected a numeric order_key after the switch to a BigInt-derived string.
The queues list and queue detail pages now use the shared TimeFilter (any preset period or a custom date range) and everything on the page follows it: header tiles, per queue metric columns, charts, and stats. The custom period buttons, hand rolled chart cards, and duplicated metric fetch loops are replaced by the ChartCard and Chart primitives, UsageSparkline, and a shared useMetricResourceQuery hook. The ClickHouse list queries take an explicit end bound so fixed ranges query only their window.
Queries using deltaSumTimestampMerge failed with an unknown function error, which broke the queue detail stats and the started counts on the built in Queues dashboard.
The queues list header tiles now render the same line chart, grid, and tooltip as the rest of the metrics charts instead of a row sparkline, with the headline value in the tile header. The env saturation tile draws the environment concurrency limit and burst limit as labeled reference lines. Chart tooltips keep a gap between the series label and the value, and the shared line chart gains showDots and referenceLines options.
Adds an Allocation tab to the Queues page (behind the queue metrics UI flag): overview cards, a burst-aware capacity bar showing each queue allocation and its live usage in a distinct color, an inline-editable limits table with per-queue locks, load-weighted auto-balance, and a review dialog that bulk-applies limits as overrides through the existing concurrency system. The queue list now defaults to Busiest ordering (with Backlog and Name options). ClickHouse ranks queues by activity over the last 15 minutes and returns just the requested page of names, so the cost per page is one small aggregate regardless of environment size; idle queues follow in name order and any failure falls back to name ordering. The classic page keeps plain name order.
The fallback WHERE injection only targeted the top-level SELECT, so a query shaped as an outer aggregation over a FROM subquery failed to compile: the time column only exists inside the subquery. Descend into the subquery so the fallback lands next to the table reference.
Adds two rollups fed from the raw landing table: a per-queue 5-minute tier and an environment-level 1-minute tier (gauges plus TDigest wait quantiles). Ranking now reads the 5m tier and returns the page and the ranked total in one windowed query instead of two scans. The 5m materialized view reads raw rather than cascading off the 10s table: deltaSumTimestamp states hold a single first/last segment, so merging states in an MV's hash-ordered GROUP BY double-counts bridging spans. For the same reason the env tier carries no counter columns, and env-wide counter totals must group by queue before summing.
The built-in queues dashboard's enqueued vs started chart merged counter states across queues, which mixes unrelated cumulative counters and returns wrong totals; it now merges per queue and sums outside. Env header tiles and saturation charts read the environment rollup, so their cost no longer scales with queue count, and coarse-bucket ranges are served from the 5m rollup automatically. Queue list ranking runs as one query, time bounds are aligned to the bucket grid, and repeated auto-refresh reads share ClickHouse query-cache entries.
… rollup The env rollup's win comes from dropping the queue dimension, not from coarser buckets: row count is queue-independent (~8640/day/env), so full 10-second granularity stays cheap at any range. Env header tiles and saturation charts now resolve short-range detail exactly like the per-queue charts, and the current-value tiles read the latest 10-second bucket instead of a minute-wide one.
The simulator's --reset only cleared the raw and 10s tables, leaving stale rows in the 5m and env rollups. It also force-merges the rollups after seeding so current-value widgets read cleanly.
…ne-shots The review stand can now recover on command for the health_recovery watch demo: a mode file flips the heartbeat's gauges per tick, --recover flushes the degraded story from the report window (raw + rollups, Redis depth included) and --degrade restores it, purging the pinned story from the baseline so the stand actually reads degraded again.
New DASHBOARD_AGENT_WATCH alert type on the standard channels (email/Slack/webhook), configurable on the Alerts page. The watcher task calls back after a fired transition (token-authenticated, idempotent, user re-authorized against the watch's environment); the alert job is payload-carried like error-group alerts. Emails carry a signed one-click unsubscribe link (GET confirms, POST mutates). New UAT-scoped alerts API lets the agent list, create, and disable subscriptions; plan/flag gate enforced at both subscribe and delivery. The in-dashboard notification badge stays ungated.
… history list A chat with an unread wake shows a dot and a brighter title and rises to the top of History; opening it clears the highlight (optimistically, and masked across the read/reload race).
The createWatch response now says whether the project already has a watch-fire alert subscription (subscribed / none / unavailable); on none the agent's watch confirmation ends with a one-line offer, on unavailable it stays silent, and the after-fire offer remains for older watches.
A history row now shows what's ongoing in that chat: a spinner while the agent is answering (client-known, active chat only), a magnifier for an open investigation (latest revision wins), an eye for an active watch.
…er everywhere - A wake message now opens with an unmistakable banner (tone by outcome and watch kind: all clear / needs attention / expired), composed via a new ChatWakeSlot micro-layout; gallery section added. - A wake arriving while the dashboard is open raises a persistent toast (manual close only, one per wake, summary above three) with an Open chat action. - Every report footer now ends like the diagnosis card: a Next steps heading with the buttons in one row and stated options as a dimmed line; docs entries without a URL fall back to their canonical page, and the stale variant's watch offer is a real Watch recovery button again.
… the docs button A card's watch button now sends a visible request the agent answers with schedule_watch — the transcript shows what was asked, the agent confirms, and the email-alert offer applies. Docs footer entries render as the docs button whatever shape their link arrived in; cited references keep a link via a status-page fallback.
…tions state the lifetime The chat's watch list now includes fired/expired watches (chips still filter to active), so a wake banner can tell good news from bad instead of falling back to the neutral wording. The agent's watch confirmation must now always say it fires once and exactly when it gives up.
…ved slot Every chat row keeps the leading slot so titles align; watching spins like thinking (the hover title says which) and the short status text stays on hover.
…n through The endpoints require chatId (the same chat-scoped floor watch creation uses); the tools sent none and every call died as a 400.
…umber in one column The throughput label now sits vertically centered against its value+breakdown stack, and 842/830 start on the same vertical as +12/min and the other rows' values; sub labels follow their numbers.
…s, UI map, hands-on walkthrough
…aks plainly One conversational message with the watch's note, a lime CTA, and the same skeleton as the billing-limit email; the fielded fact sheet is gone and the unsubscribe link keeps its wiring with footer styling.
…d to mid-column, number in the value column
'Watch update — all clear / needs your attention', toned by kind; the identity moves to the details line and the subject follows suit.
…with starred scenarios
🦋 Changeset detectedLatest commit: 1d15fe3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 27 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedToo many files! This PR contains 340 files, which is 40 over the limit of 300. To get a review, narrow the scope: Usage-priced reviews support at most 300 files. ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (340)
You can disable this status message by setting the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…t button; URLs are links The prompt now treats earlier turns' pages as history — deictic questions re-read the current page every turn, and page explanations end with a matching docs link. The report's contact action falls back to the contact page as a real external button instead of an ask round-trip, and answers that point at a URL carry it as a link.
…ress line, wake toast opens its chat as an agent Callout - navigate intents and navigate_to outputs resolve trigger:// URIs server-side and navigate in place; same-origin citation buttons navigate instead of opening a new tab. - The transcript autoscrolls on send and follows streaming near the bottom; a store-order stable merge stops messages landing mid-chat after a page change (server-side single-read follow-up noted). - The generic Working line yields to a tool-specific one. - The wake toast is the new agent Callout variant (chat icon) and opens the exact chat that woke.
…nside the label column
An in-flight tool call now shows a compact pill (per-tool phrase + spinner, watch-chip visual language) instead of raw streaming JSON — covering render_view and get_report, the biggest offenders. Completed and error states render as before; gallery in-flight examples reworked and a pill line-up section added.
An AI assistant in a side panel on every dashboard page, behind the dashboard-agent feature flag. It reads runs, errors, queues, deploys and health through the public API (read-only, delegated user token), answers with rich cards, and can keep watching things after the conversation ends.
What's inside
@internal/dashboard-agent-contracts(trigger:// URI grammar, intents, watch specs, block envelope), investigations + watches tables, head-start reliability fix, eval sample-rate gate.get_reportrenders the deterministic health report as a card (metric grid, sparklines, Next steps button row); stale telemetry is flagged and never trusted for advice.DASHBOARD_AGENT_WATCHalert type on the standard channels with one-click unsubscribe; the agent offers, lists and disables subscriptions on request; ungated in-dashboard signal: persistent toast, unread dot on the chat launcher, unread-first history with per-chat status icons.db:seed:agent-examples, with--heartbeat/--degrade/--recoverfor demos).How to review
GUIDEBOOK.md — 10-minute local setup and a hands-on walkthrough of every case. Component gallery at
/storybook/agent-ui.Notes
canAccessDashboardAgent; no behavior change with the flag off.--heartbeatmode is a review-stand crutch and will be removed before merge.