feat(cli): add metrics resources command for CPU, memory and GPU memory - #93
Open
jonoirwinrsa wants to merge 5 commits into
Open
feat(cli): add metrics resources command for CPU, memory and GPU memory#93jonoirwinrsa wants to merge 5 commits into
jonoirwinrsa wants to merge 5 commits into
Conversation
jonoirwinrsa
force-pushed
the
feat/cli-json-output
branch
from
August 9, 2026 22:04
27b5592 to
5d67fee
Compare
jonoirwinrsa
force-pushed
the
feat/cli-metrics
branch
from
August 9, 2026 22:04
db03a6c to
e8e2f4b
Compare
Agents driving `cerebrium deploy` have to scrape fixed-width text tables to learn anything about a deployment. Only `status` supported `--output json`. Add a shared output-format helper in internal/ui and wire it through apps list/get, containers list, runs list, projects list, secrets list and files ls. JSON emits the api structs as-is, including the fields the tables drop. `status` is refactored onto the helper rather than keeping its own copy. `secrets list --output json` omits values unless --show-values is passed, so it leaks no more than the table does. The spinner is skipped for JSON output so no frames land in the payload stream. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The output plumbing shipped with no tests, verified only by hand against a live account. That does not survive the next refactor, and one of the behaviours is security relevant. `secrets list --output json` omits values unless --show-values is passed. Nothing pinned that, so collapsing the payload back to the raw map would start printing every secret in the project while the table still hid them. Extracts the shaping into newJSONSecrets and covers it: values hidden by default, present when asked, an empty value kept distinguishable from a hidden one, key order preserved, and no secrets encoding as [] rather than null. Also covers ParseOutputFormat (defaults, both flag forms, unsupported values, and that the error names the accepted formats), PrintJSON (indentation, trailing newline, empty slice as [], nothing written when encoding fails, stable across runs), and the nil-receiver spinner guard the JSON paths depend on. Both behaviours were mutation checked: forcing values to always be included and removing the nil guard each fail the corresponding test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jonoirwinrsa
force-pushed
the
feat/cli-json-output
branch
from
August 10, 2026 20:01
2e427c2 to
aee5c94
Compare
An agent that has just deployed an app has no way to tell whether the hardware in cerebrium.toml is the right size. Add `cerebrium metrics resources APP`, backed by the resource-metrics endpoint. Reports peak usage over a window: CPU in cores, memory and GPU memory (VRAM) in GB. Defaults to the last hour; --since, --start/--end, --container-id and --resolution narrow it. Table output is a summary rather than a thousand datapoints; --output json adds the raw series alongside it. The endpoint relays raw query values, which arrive as JSON strings, and pads gaps with null, so MetricValue decodes from either form and marshals back out as a number. NaN and infinities decode as absent. A metric that never reported prints "-" rather than 0.00, which would read as a measurement rather than the absence of one. Scoped to a single container the API returns one series per metric, named after the metric itself, so summary cells are matched to columns by position and the header collapses to a single PEAK column. Also lifts normalizeAppID, which had been copied into three files, into api.NormalizeAppID, moving its test along with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jonoirwinrsa
force-pushed
the
feat/cli-metrics
branch
from
August 10, 2026 20:02
e8e2f4b to
8995535
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
An agent that has just run
cerebrium deploycan now see whether its app is up (#92), but not whether the hardware incerebrium.tomlis the right size.cerebrium metrics resources APPreports the three numbers that answer it — CPU, memory, and GPU memory (VRAM) — from theresource-metricsendpoint.Defaults to the last hour.
--since,--start/--end,--container-idand--resolutionnarrow it;--output jsonreturns the summary plus the raw series so an agent can do its own analysis.Deliberately narrow: the backend also exposes latency percentiles, startup time, cost, queue depth and per-container CPU/memory. Those can follow. (The
/metrics/*percentile endpoints are also behind a per-project feature flag, which is its own conversation.)Two things worth reviewing
The endpoint's
dataarrays are not numbers. It relays raw query values, and those arrive as JSON strings, withnullfor padded gaps. The web client's(number | null)[]type is wrong about this — JS coerces on the way into the chart, so it never surfaced. Go doesn't, soMetricValuedecodes from string, number or null and marshals back out as a plain number.NaN/±Infdecode as absent rather than blowing upjson.Marshal.Absence vs zero. A series that never reported prints
-, not0.00. A GPU row of0.00would claim we measured zero VRAM in use, which is a different statement from "no samples". A genuine measured0is still shown as0.00; there's a test pinning that.Also lifts
normalizeAppID— which had been copy-pasted into three files — intoapi.NormalizeAppID, with its test moved alongside. Adding a fourth copy for this command seemed like the wrong direction.Testing
go build,go vet,go test ./...all clean. No golden files regenerated. New unit tests coverMetricValuedecoding (string/number/null/empty/NaN/Inf/garbage), number-form marshalling, window resolution, and the summary/column logic.Verified against prod on a real H100 app over a window when it was actually serving:
CPU,Memory,GPU), so matching cells to columns by name made Memory and GPU render-despite having data. Cells are now matched by position and the header collapses toPEAK. There's a regression test.-for this app. The series are present but every sample is null, i.e. no GPU samples came back for that window — the web client sends identical params, so this is upstream, not a gap in the request. I could not verify a non-null GPU number, so if you have an app that reports VRAM it's worth a sanity check before merge.--resolution,--startand--outputvalues all produce clean validation errors;-o jsonpiped with stdin closed is parseable (no spinner bytes).