feat(runner): track per-sandbox host-side file descriptor usage - #5001
feat(runner): track per-sandbox host-side file descriptor usage#5001mu-hashmi wants to merge 4 commits into
Conversation
Signed-off-by: Muhammad Hashmi <mhashmi@berkeley.edu>
Signed-off-by: Muhammad Hashmi <mhashmi@berkeley.edu>
Signed-off-by: Muhammad Hashmi <mhashmi@berkeley.edu>
|
View your CI Pipeline Execution ↗ for commit 2df2ffe
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Pull request overview
This PR adds per-sandbox host-side file descriptor (FD) telemetry to the runner’s Prometheus /metrics endpoint, sampled on the existing allocated-resources snapshot tick, and includes operator warning logs when per-sandbox FD usage crosses a configurable threshold.
Changes:
- Introduces new per-sandbox Prometheus gauges for open FDs, FD soft limit (RLIMIT_NOFILE), usage percent, and runtime-helper FD attribution.
- Implements Linux-only FD sampling by mapping container init PID → container cgroup members → per-process FD counts + RLIMIT_NOFILE, plus best-effort runtime-helper attribution.
- Adds config wiring for
SANDBOX_FD_USAGE_WARNING_THRESHOLD_PERCENTand warning hysteresis/re-warn tracking + pruning.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| apps/runner/pkg/common/metrics.go | Adds new per-sandbox FD-related Prometheus gauge vectors. |
| apps/runner/internal/metrics/fd.go | Implements proc/cgroup-based FD sampling, runtime-helper attribution, and warning state tracking. |
| apps/runner/internal/metrics/fd_test.go | Adds unit tests for FD sampling logic, cgroup resolution, helper attribution, and warning hysteresis/rewarn/prune behavior. |
| apps/runner/internal/metrics/collector.go | Wires FD sampling into the allocated-resources snapshot loop; updates container inspect usage and adds cleanup/prune handling. |
| apps/runner/go.mod | Promotes github.com/prometheus/procfs to a direct dependency. |
| apps/runner/cmd/runner/main.go | Passes the configured warning threshold into the metrics collector. |
| apps/runner/cmd/runner/config/config.go | Adds envconfig/validation for the FD usage warning threshold percent. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| sandboxId := strings.TrimPrefix(containerJSON.Name, "/") | ||
|
|
||
| usage, err := sampleSandboxFdUsage(procRoot, cgroupRoot, containerJSON.State.Pid) | ||
| if err != nil { | ||
| return 0, 0, 0, err | ||
| c.log.DebugContext(ctx, "Failed to sample sandbox fd usage", "sandbox_id", sandboxId, "error", err) | ||
| return | ||
| } | ||
|
|
||
| seen[sandboxId] = struct{}{} | ||
| common.SandboxOpenFds.WithLabelValues(sandboxId).Set(float64(usage.OpenFds)) |
There was a problem hiding this comment.
Fixed in 2df2ffe: presence is recorded before sampling, so a transient sampling failure no longer prunes warn state; gauges are dropped for the failed tick only.
There was a problem hiding this comment.
3 issues found across 7 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
…d fix edge cases Signed-off-by: Muhammad Hashmi <mhashmi@berkeley.edu>
2c15a7f to
b40f732
Compare
TL;DR: the runner now samples per-sandbox host-side file-descriptor usage on its existing 5s tick and exposes Prometheus gauges plus a rate-limited operator warning - zero API surface change.
Description
During the fd-exhaustion incident, host-side fd budgets were exhausted while guest-side indicators looked fine; operators had no per-sandbox visibility. This PR adds it:
RLIMIT_NOFILE./metricsendpoint:sandbox_open_fds,sandbox_fd_limit(0 = every sampled process unlimited; dashboards must guard division),sandbox_fd_usage_percent(worst-process ratio - RLIMIT_NOFILE is per-process, so the worst process is what actually hits EMFILE), labeled bysandbox_id.SANDBOX_FD_USAGE_WARNING_THRESHOLD_PERCENT(default 70, validated 1-100), with a hysteresis band and 10m re-warn interval; recovery logs once; label sets and tracker state are pruned when sandboxes disappear.sandbox_runtime_helper_open_fdsgauge; failures degrade to absent metrics, never errors.Known limits: nested-cgroup sandboxes undercount (members enumerated non-recursively); reading
/proc/<pid>/fdrequires the privileges the runner already runs with.Review guide
Suggested order:
apps/runner/internal/metrics/fd.go- sampling math, limit parsing, worst-process computation, warn tracker (risk center: warn-state lifecycle across failure ticks and the hysteresis floor, reachable across the full 1-100 threshold range).apps/runner/internal/metrics/collector.go- tick integration, presence-before-sampling, helper attribution gate.No generated files.
Commit map
Related PRs
Independent. Sibling fd-incident PRs: #5002 (degradedReason surfacing), #5003 (daemon shell resolution).
Validation
GOOS=linux go build ./...,gofmtclean,golangci-lintv2.6.2 zero issues,go work syncno drift.Closes #4995