Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ headless agent modes, and a Cobra CLI.
- Keep comments short. If code needs a paragraph to explain its structure, simplify it.
- Never run state-changing Git commands. Do not stage, commit, push, tag, stash,
create branches, or create worktrees.
- Always use the `golang-master` skill when writing Go.
- Name every unexported Go function with an `Internal` suffix.
- Put public/shared Go types in the top-level `types/` module.
- Put reusable helper utilities under `backend/pkg/utils/` in the appropriate package.
Expand Down
35 changes: 15 additions & 20 deletions backend/api/ws/system_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (h *WebSocketHandler) acquireSystemStatsSamplerInternal(ctx context.Context

collect := h.systemStatsCollector
if collect == nil {
collect = h.collectSystemStats
collect = h.collectSystemStatsInternal
}

go func() {
Expand Down Expand Up @@ -215,13 +215,13 @@ func (h *WebSocketHandler) runSystemStatsSamplerInternal(ctx context.Context, wa
}
}

// collectSystemStats gathers all system statistics.
func (h *WebSocketHandler) collectSystemStats(ctx context.Context) systemtypes.SystemStats {
// collectSystemStatsInternal gathers all system statistics.
func (h *WebSocketHandler) collectSystemStatsInternal(ctx context.Context) systemtypes.SystemStats {
cpuUsage, _ := h.cpuCache.Load()

cpuCount := h.getCPUCount()
memUsed, memTotal := h.getMemoryInfo()
cpuCount, memUsed, memTotal = h.applyCgroupLimits(cpuCount, memUsed, memTotal)
cpuCount, memUsed, memTotal = h.applyCgroupLimitsInternal(ctx, cpuCount, memUsed, memTotal)
diskUsed, diskTotal := h.getDiskInfo(ctx)
hostname := h.getHostname()
gpuStats, gpuCount := h.getGPUInfo(ctx)
Expand Down Expand Up @@ -281,22 +281,17 @@ func (h *WebSocketHandler) getMemoryInfo() (uint64, uint64) {
return used, memInfo.Total
}

// applyCgroupLimits applies cgroup limits when running in an LXC (or similar)
// container where the limits represent the real hardware budget.
//
// It is intentionally a no-op inside Docker: Docker's --cpus / --memory flags
// set artificial cgroup constraints that are unrelated to the host totals we
// want to display. gopsutil already reads the correct host values there (via
// the bind-mounted /proc). Applying cgroup limits on top would produce the
// "#2343 regression" where the dashboard shows "512 MB RAM" while the host
// has 32 GB (#1110).
//
// In LXC the situation is the opposite: gopsutil reads the host's /proc
// (which shows the physical machine's RAM/CPU) rather than the slice of
// resources actually allocated to the LXC guest. The cgroup limits ARE the
// correct numbers to show.
func (h *WebSocketHandler) applyCgroupLimits(cpuCount int, memUsed, memTotal uint64) (int, uint64, uint64) {
// applyCgroupLimitsInternal uses guest resources without applying Docker's
// per-container limits to host statistics.
func (h *WebSocketHandler) applyCgroupLimitsInternal(
ctx context.Context, cpuCount int, memUsed, memTotal uint64,
) (int, uint64, uint64) {
if cgroup.IsDockerContainer() {
if h.systemService != nil {
if used, total, ok := h.systemService.GetDockerHostMemory(ctx); ok {
return cpuCount, used, total
}
}
return cpuCount, memUsed, memTotal
}
cpuCount = applyCPUAffinityLimitInternal(cpuCount)
Expand Down Expand Up @@ -326,7 +321,7 @@ func (h *WebSocketHandler) applyCgroupLimits(cpuCount int, memUsed, memTotal uin
// the only signal of the cores actually assigned — including gap bindings like
// CPU1+CPU7 — while /proc/cpuinfo shows the whole host (#3161). runtime.NumCPU
// reads that mask at process start. Not applied inside Docker, matching
// applyCgroupLimits' host-totals convention there.
// applyCgroupLimitsInternal's host-totals convention there.
func applyCPUAffinityLimitInternal(cpuCount int) int {
if n := runtime.NumCPU(); n > 0 && (cpuCount == 0 || n < cpuCount) {
return n
Expand Down
36 changes: 18 additions & 18 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ require (
github.com/stretchr/testify v1.12.1
github.com/subosito/gotenv v1.6.0
github.com/wneessen/go-mail v0.8.1
go.getarcane.app/acfs v0.5.0
go.getarcane.app/builds v0.4.0
go.getarcane.app/docker/convert v0.3.0
go.getarcane.app/kit v0.1.0
go.getarcane.app/streams v0.4.2
go.getarcane.app/sys/cgroup v0.2.0
go.getarcane.app/sys/crypto v0.2.0
go.getarcane.app/updater v0.8.0
go.getarcane.app/acfs v0.5.1
go.getarcane.app/builds v0.4.1
go.getarcane.app/docker/convert v0.3.1
go.getarcane.app/kit v0.1.1
go.getarcane.app/streams v0.4.3
go.getarcane.app/sys/cgroup v0.2.3
go.getarcane.app/sys/crypto v0.2.1
go.getarcane.app/updater v0.8.1
go.uber.org/fx v1.24.0
go.yaml.in/yaml/v4 v4.0.0-rc.6
golang.org/x/crypto v0.56.0
Expand Down Expand Up @@ -147,10 +147,10 @@ require (
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
github.com/depot/depot-go v0.5.3 // indirect
github.com/docker/buildx v0.36.1 // indirect
github.com/docker/docker-credential-helpers v0.9.8 // indirect
github.com/docker/docker-credential-helpers v0.9.9 // indirect
github.com/docker/go-connections v0.8.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.10.2 // indirect
github.com/ebitengine/purego v0.11.0 // indirect
github.com/eclipse/paho.golang v0.23.0 // indirect
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
Expand Down Expand Up @@ -204,7 +204,7 @@ require (
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
github.com/lestrrat-go/option/v3 v3.0.0-alpha1 // indirect
github.com/lucasb-eyer/go-colorful v1.4.1 // indirect
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect
github.com/lufia/plan9stats v0.0.0-20260802145828-341c2f0c90b5 // indirect
github.com/mattn/go-colorable v0.1.15 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
Expand Down Expand Up @@ -240,18 +240,18 @@ require (
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/power-devops/perfstat v0.0.0-20260805114148-88456608a4f6 // indirect
github.com/prometheus/client_golang v1.24.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.70.1 // indirect
github.com/prometheus/client_model v0.6.3 // indirect
github.com/prometheus/common v0.71.0 // indirect
github.com/prometheus/procfs v0.22.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/samber/go-singleflightx v0.3.2 // indirect
github.com/samber/lo v1.53.0 // indirect
github.com/samber/oops v1.18.1 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.11.0 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.11.1 // indirect
github.com/sergi/go-diff v1.4.0 // indirect
github.com/sethvargo/go-retry v0.4.0 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
Expand Down Expand Up @@ -298,8 +298,8 @@ require (
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260831171406-18b4a7587f8a // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260904194346-d0f1323225a4 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260904194346-d0f1323225a4 // indirect
gopkg.in/ini.v1 v1.67.3 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
Loading
Loading