feat: add the /report health report (get_report MCP tool + CLI + API)#4327
feat: add the /report health report (get_report MCP tool + CLI + API)#4327kathiekiwi wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 61f9bae 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 skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughAdds a deterministic 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
fd73141 to
8f7a066
Compare
@trigger.dev/build
trigger.dev
@trigger.dev/core
@trigger.dev/python
@trigger.dev/react-hooks
@trigger.dev/redis-worker
@trigger.dev/rsc
@trigger.dev/schema-to-json
@trigger.dev/sdk
commit: |
072fa30 to
1306825
Compare
150c7ff to
2e4d964
Compare
164ee14 to
682ceb6
Compare
c045c86 to
7d175ab
Compare
7d175ab to
f1337fa
Compare
f1337fa to
e3c4064
Compare
976c4cc to
07542ab
Compare
1468faa to
ece0ce7
Compare
ece0ce7 to
3dc5fa9
Compare
3dc5fa9 to
59a8ebd
Compare
59a8ebd to
61f9bae
Compare
There was a problem hiding this comment.
Devin Review found 3 new potential issues.
⚠️ 1 issue in files not directly in the diff
⚠️ Report baseline cache grows without bound as environments accumulate (apps/webapp/app/presenters/v3/reports/health/health-data.ts:166-167)
Cached baseline query results are stored per environment (baselineCache.set at apps/webapp/app/presenters/v3/reports/health/health-data.ts:166-167) but expired entries are only ever replaced on a repeat request for the same key, never removed, so entries for environments that stop requesting reports linger in memory forever.
Impact: A long-running server that serves health reports across many environments slowly accumulates memory that is never reclaimed.
Cache-eviction mechanism
The module-level Map at apps/webapp/app/presenters/v3/reports/health/health-data.ts:141 is written on every cache miss for a BASELINE_PERIOD query (two distinct baseline query strings per env). The only expiry check is on read at health-data.ts:149-151, which just ignores stale entries; nothing deletes them. There is no size cap and no periodic sweep, so the number of retained entries scales with the total number of distinct environments that have ever fetched a report, not the active set. Each entry retains the query rows and timeRange.
| const ageMs = input.liveness.telemetryAgeMs; | ||
| const livenessSeverity: Severity = | ||
| ageMs === null // no signal to assess — unknown, not a hard stale (never trust-guards) | ||
| ? "warn" | ||
| : ageMs > t.liveness.staleMs | ||
| ? "crit" | ||
| : ageMs > t.liveness.freshMs | ||
| ? "warn" | ||
| : "ok"; |
There was a problem hiding this comment.
🔍 Quiet/new environments render an overall yellow verdict via null-freshness warn
When input.liveness.telemetryAgeMs is null (no telemetry signal at all — e.g. a brand-new or quiet env), buildMetrics assigns liveness severity warn (apps/webapp/app/presenters/v3/reports/health/health.ts:227-235). aggregateSummary then takes maxSeverity(flow, execution, liveness) (health.ts:679), so even when flow and execution are perfectly healthy the overall summary severity becomes warn and the liveness marker renders 🟡 (data freshness unknown). The comment at health.ts:229 intentionally chose warn over a hard stale so it never trust-guards, but the aggregate effect is that a fine-but-idle environment surfaces as a non-green report. Worth confirming this is the desired UX (vs. treating no-signal liveness as neutral in the summary).
Was this helpful? React with 👍 or 👎 to provide feedback.
| environment: completable(z.string().optional(), (value) => | ||
| ENVIRONMENTS.filter((e) => e.startsWith(value ?? "")) | ||
| ), | ||
| period: ReportPeriodSchema.optional(), |
There was a problem hiding this comment.
🔍 MCP prompt period argument uses a ZodEffects schema unlike the completable string args
In registerPrompts, the key and environment prompt arguments are wrapped with completable(z.string().optional(), ...), but period is passed as ReportPeriodSchema.optional() (packages/cli-v3/src/mcp/prompts.ts:30), where ReportPeriodSchema is a z.string().regex().refine() i.e. a ZodEffects<ZodString>. MCP prompt argument shapes expect plain string-typed schemas; a ZodEffects may not be introspected the same way the SDK handles a ZodOptional<ZodString>/completable when generating the prompt's arguments metadata. This is likely fine at runtime (the incoming value is a string and the refine just validates the range), but worth verifying against the installed @modelcontextprotocol/sdk version that a refined string is accepted as a prompt arg.
Was this helpful? React with 👍 or 👎 to provide feedback.
Overview
Adds the first Report —
health. The server computes a deterministic verdict and renders it as text + unicode sparklines.healthseparates flow (is work starting?), execution (are the runs that start succeeding?), and liveness (is the telemetry fresh?), each with a headline verdict and a suggested next action — no LLM in the verdict, so there's nothing to hallucinate.Surfaces:
get_reportMCP tool — markdown with sparklines + 🟢/🟡/🔴 status markers (or ANSI viacolor).reportMCP prompt — a slash command in hosts that support prompts.trigger report [key]CLI — colourised in a real terminal, plain markdown when piped.GET /api/v1/reports/:key—format=markdown|ansi|json.Flow is diagnosed by a cause tree (env-limit saturation, queue throttling, key starvation, trigger spike, dequeue stall) off measured queue metrics, with a runs-snapshot fallback. One
ReportViewModel, rendered to markdown / ANSI / JSON.Also:
trigger mcpnow always starts the server — the interactive install wizard is gated behindtrigger mcp --install. Previously a TTY dropped into the wizard, so MCP hosts that spawn the server over a PTY never got a server and timed out.Screenshots
Degraded — env concurrency-limit saturation:
Healthy:
Testing
Automated (
apps/webapp/test/*)reportHealth.test.ts— 14 tests.interpret()is pure (fixed fixtures, no IO / clock / LLM):(last 40 min), queue attribution, exclusions (incl.nothing dead-lettered), read chain, driving-metric annotation, footer (raise limit + "do nothing, drains in ~2.3 min"), full markdown snapshot.nothing_to_dofooter, full markdown snapshot.dequeue_stall,env_limit_saturation,queue_limit_throttling,key_starvation,trigger_spike, and the v1-symptom fallback each select the correct cause.unknown+ acritsummary (never a false-green from a silent feed).✓/⚠/✕) + ANSI colour, never the markdown status emoji.isPendingIncreasingtrend helper.reportHealthData.test.ts— 5 tests. DrivesloadHealthInputthrough its query seam (HealthDeps) — source selection, snapshot fallback on empty and on throw (the query-concurrency 500 guard), dlq parsing (0vs unmeasurednull), andwindowMinutesfrom the resolved (clipped) time range. The SQL/TRQL translation is owned + tested by the query service; the ClickHouse MV aggregation by the@internal/clickhousepackage tests.