Skip to content

grafos placements

Inspect the scheduler’s placement log. Each row summarizes one placement decision with a per-typed-reason rollup of rejected candidates. Use --json for the full per-candidate detail.

For the full operator runbook including the typed-reason vocabulary and common jq queries, see the admission and placement explanations runbook.

grafos placements

Placement log: read `/api/v1/placements` and render the scheduler's recent placement decisions. Each row summarizes one placement decision with a per-typed_reason rollup of rejected candidates (slice-36 vocabulary). Use `--json` for the full per-candidate detail
Usage: grafos placements [OPTIONS]
Options:
--fabric <FABRIC> Fabric address (host:port). Overrides GRAFOS_FABRIC env var [env: GRAFOS_FABRIC=]
--scheduler <SCHEDULER> Scheduler URL. Falls back to `GRAFOS_SCHEDULER`, then to the Tenura-hosted credentials when that context applies [env: GRAFOS_SCHEDULER=]
--bearer <BEARER> FabricAdmin bearer token (alternative to mTLS) [env: GRAFOS_BEARER=]
--cert <CERT> Client certificate (PEM) for mTLS [env: GRAFOS_CERT=]
--wide Show additional columns in table output
--key <KEY> Client private key (PEM) matching --cert [env: GRAFOS_KEY=]
--no-color Disable color output
--ca <CA> CA bundle (PEM) used to verify the scheduler's TLS cert [env: GRAFOS_CA=]
--pool <POOL> Pool name (default: "default") [default: default]
--limit <LIMIT> Maximum rows to render in table mode. JSON mode returns every entry the scheduler reported [default: 50]
--reason <REASON> Filter to placements that contain at least one rejected candidate whose `typed_reason` matches one of the supplied snake_case labels. Repeatable: `--reason placement_policy_excluded --reason node_address_unknown` matches either. Unknown labels fail the parse with a typed error listing every valid label
--json Emit JSON. The body is byte-passthrough of the scheduler's response so existing `jq` scripts keep working unchanged. JSON mode is the only path that surfaces per-candidate `typed_reason` today; the table mode summarizes at the placement level
-h, --help Print help
-V, --version Print version

Per-candidate typed reasons

Each rejected candidate in the placement log carries a stable typed_reason snake_case label. The default table mode rolls candidates up by reason; --json exposes the per-candidate detail.

Placement-specific labels (in addition to the admission-side set):

  • placement_policy_excluded — top-level placement authorization, active-degradation set exclusion, or pinned-strategy mismatch. Prose reasons carries the specific sub-reason; SIEM rules alert on the typed label across all of them.
  • node_address_unknown — operational state, scheduler doesn’t have a control-plane address for the candidate. Distinct from policy exclusions so dashboards alert on the two classes separately.

Default table format

TIMESTAMP | TENANT | RESOURCE | BYTES | STRATEGY | OUTCOME | CHOSEN | CANDIDATES

The CANDIDATES column rolls up rejected candidates by typed_reason in alphabetical order:

1 accepted
1 accepted, 3 rejected (node_address_unknown:1, placement_policy_excluded:2)

Operators scanning the table see the dominant rejection class without needing --json.

Common jq queries

Terminal window
# Per-candidate rejection rollup across all placement records.
grafos placements --json \
| jq -r '.[].candidate_explanations[]
| select(.decision == "rejected")
| .typed_reason' \
| sort | uniq -c | sort -rn
# Placements where ALL candidates were rejected.
grafos placements --json \
| jq '.[] | select(
[.candidate_explanations[] | select(.decision == "accepted")]
| length == 0)'