Repository navigation
feat(mcp): query Google Cloud metrics live with PromQL - #1478
JeremyFunk wants to merge 9 commits into
Conversation
find_gcp_metrics searches a project's Cloud Monitoring metric types or describes one with a starter query; query_gcp_promql runs PromQL over a window or at an instant through GcpPromQlService. The chat renders range results as a chart. The ai Worker binds MAPLE_GCP_SERVICE_ACCOUNT_KEY.
Explicit bucket_seconds is validated, not clamped; one error tail for both query kinds; the describe output reuses the descriptor's fields; label values are quoted and descriptions capped; gauge distributions skip rate; chart series keep __name__ so none collide.
A bucket_seconds too fine for the window widens to 500 points instead of a 400, which also bounds the chat payload. No project to read is unavailable, not a retry. Describe suggestions skip names Google would refuse; the instant lookback hint shows only on instant queries.
Maple review🟢 Confidence 8/10 · likely safe to merge Two public MCP tools that run PromQL live against the org's own Google Cloud Monitoring projects, with a chart for range results and a table for instant ones. Wiring, error mapping and the chart rows are consistent with the existing api path; none of the open
Before merge
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Telemetry this change adds and removes (2)
What was checked
Observability coverage: 3 of 3 changes observable
|
|
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 configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
Maple review🟢 Confidence 7/10 · likely safe to merge Adds two public MCP tools that read Google Cloud Monitoring metrics live through Google's PromQL API (
Before merge
Findings🟠 Warning · F1 · Chat instant table shows the oldest point, not the value at
|
| Change | Kind | Observable | Evidence |
|---|---|---|---|
MCP tool call find_gcp_metrics |
Server | yes | Handler span Effect.fn("McpTool.findGcpMetrics") plus the dispatcher's maple.mcp.tool attribution (dispatcher.ts:122) |
MCP tool call query_gcp_promql |
Server | yes | Handler span Effect.fn("McpTool.queryGcpPromql"), maple.ai.kind and result.seriesCount attributes |
| Google Cloud Monitoring PromQL read per project | Client | yes | GcpPromQlService.queryRange/queryInstant Effect.fn spans via the Google client in packages/backend |
890f83e · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
| headers: ["Series", "Value"], | ||
| rows: output.data.series.map((series) => [ | ||
| seriesKey(series.labels), | ||
| String(series.points[0]?.[1] ?? "-"), |
There was a problem hiding this comment.
Warning
Chat instant table shows the oldest point, not the value at end_time
F1 · Warning · correctness
An instant query whose selector is a range vector (sum(rate({"..."}[5m]))) comes back as a matrix with several points per series, and points[0] is the earliest, so the chat table prints a value from as far back as the selector's range while the tool's own table (apps/ai/src/mcp/tools/gcp-promql.ts:388, last point) and the "instant: one value per series at end_time" contract report the latest. Read the last point, as the tool does.
| String(series.points[0]?.[1] ?? "-"), | |
| String(series.points.at(-1)?.[1] ?? "-"), |
🤖 Prompt to fix with an AI agent
In `apps/web/src/components/ai-elements/renderers/tool-renderer.tsx:192`: Chat instant table shows the oldest point, not the value at `end_time`.
An `instant` query whose selector is a range vector (`sum(rate({"..."}[5m]))`) comes back as a matrix with several points per series, and `points[0]` is the earliest, so the chat table prints a value from as far back as the selector's range while the tool's own table (`apps/ai/src/mcp/tools/gcp-promql.ts:388`, last point) and the "instant: one value per series at end_time" contract report the latest. Read the last point, as the tool does.
Replace those lines with:
String(series.points.at(-1)?.[1] ?? "-"),
Verify the problem exists at that location before changing it, and keep the fix to those lines.
The agent can now read a customer's Google Cloud Monitoring metrics live, through Google's PromQL API, with two MCP tools. Nothing is ingested; the 5-minute poller and its
gcp.*warehouse metrics stay as they are.Stacked on #1475 (backend,
GcpPromQlService) → #1477 (live-query access) →feat/gcp-promql-widget(dashboard widget). Merge after those, by merge commit.Tools
find_gcp_metrics:search(substring of the metric type) and/ormetric(one type to describe),project,limit. Search reads one project's metric list; describe returns kind, value type, unit, monitored resource types, labels and a starter query:sum(rate(…[5m]))for DELTA/CUMULATIVE,avg(…)for GAUGE,histogram_quantile(0.95, sum by (le) (rate(…_bucket[5m])))for DISTRIBUTION, none for STRING. It adds amonitored_resourcematcher when the metric has more than one resource type, because Google refuses the selector otherwise. OutputFindGcpMetricsOutput.query_gcp_promql:query,kind(timeseriesdefault orinstantat end_time),start_time/end_time(default 1 h, at most 6 weeks, Google's usual retention),bucket_seconds(60–86400, default from the window like the other tools, about 100 points; a finer one is widened to at most 500 points per series, which also bounds the chat payload),projects. OutputQueryGcpPromQlOutput: the series sorted by last value, capped at 100 for the chat payload, plustotalSeries,projectsandfailures.project_id). Both descriptions say to aggregate withsum by/avg bybecause Google bills per series returned, and that these are live reads, separate fromlist_metrics/query_data.public(MCP transport included), read-only,openWorld. The org always comes from the request's tenant.Errors
McpInvalidInputErrorwith the messageMcpUnavailableError(gcp_live_query)McpUnavailableError(gcp_connection)McpNotReadyError, retry in 300 s, with the per-project cause and fixMcpUnavailableError(gcp_connection)McpQueryErrorOther changes
MAPLE_GCP_SERVICE_ACCOUNT_KEYthe same way api does (optionalSecret);GcpPromQlServicejoins the MCP runtime services.query_gcp_promqlrange results draw as the query chart (points merged into buckets by time); instant results as a table.find_gcp_metricsuses the generic renderer.maple://instructionsgains one tool-selection line; the MCP reference page lists both tools.Decisions
McpUnavailableError, notMcpNotReadyError: retrying cannot help until someone connects a project, which is what that error kind says.public: an MCP client with an org credential can trigger live Google reads billed to that org's own host project, like other public read tools; the 500-series cap and the edge cache bound it.McpNotReadyError: most causes are fixed by a setup-script run whose grant takes minutes to apply, and the message names the fix.Not verified without a live system
find_gcp_metrics search=run.googleapis.com/request→ describe →query_gcp_promqlwith asum by (service_name)query; the chart renders.serviceruntime.googleapis.com/api/request_count) gets a working starter query.Need help on this PR? Tag
@codesmith-botwith what you need.