Development
Start with an issue labelled good first issue: these say what should change and where. Comment on the issue before working on it. Everyone taking part follows the Code of Conduct.
Toolchain
Section titled “Toolchain”| Work on | Needs |
|---|---|
| userspace collector and CLI | Rust (stable), just |
| formatting | Rust nightly (rustfmt.toml uses unstable options) |
| eBPF programs | Rust nightly with rust-src, bpf-linker built against a matching LLVM |
| running the collector | Linux with cgroup v2 and BTF, root |
| harness and notebooks | Python 3.12+, uv |
| this site | Node.js 22.22 or later |
git clone git@github.com:<your-account>/croft.gitcd croftgit config core.hooksPath .githooksRepository layout
Section titled “Repository layout”croft/├── collector/ Rust workspace│ ├── collector/ userspace: CLI, polling, dataset writer│ │ ├── frameworks.json framework catalog, built in and replaceable│ │ └── src/│ │ ├── command/ one file per croft subcommand│ │ ├── sensing/ eBPF loading, maps, syscall names and rates│ │ ├── inspect/ /proc and cgroup readers, workload and framework│ │ ├── pipeline/ poll reporter, dataset rows, segments, /metrics│ │ ├── decision/ replicas a workload needs│ │ └── runtime/ logging, signals, terminal, HTTP│ ├── collector-ebpf/ eBPF programs (nightly Rust, bpf-linker)│ └── collector-common/ types shared by both sides├── deploy/ Docker, Kubernetes and systemd deployment├── labs/│ ├── k3s-cluster/ Ansible for the lab cluster│ └── research/experiment/ experiment harness (uv)├── website/ this site└── justfile task recipesHow a row is produced
Section titled “How a row is produced”sys_enter tracepoint ──> SYSCALL_BY_TYPE map (count per process and syscall)GPU tracepoints ──> GPU_FDS, GPU_ACTIVITY maps (GPU fds, ioctls through them)sched tracepoints ──> run queue wait per process | every 2 s, userspace reads the maps and turns the counts into per-second rates | + /proc (identity, framework, CPU, memory, I/O, network) + cgroup v2 (CPU, throttling, memory, PSI per container) | v one JSON line per process, rotated hourly into zstd segmentsjust test # unit testsjust lint # rustfmt --check (nightly) and clippy with warnings as errorsBoth build the eBPF program first. Without bpf-linker, skip it; the unit tests and clippy cover the userspace code and need no root, kernel or cluster:
cd collectorAYA_BUILD_SKIP=1 cargo test -p collectorAYA_BUILD_SKIP=1 cargo clippy -p collector --all-targets -- -D warningscargo +nightly fmt --all -- --checkWith AYA_BUILD_SKIP=1 the binary embeds an empty eBPF object: it builds, but croft run cannot load its programs. Changes to the eBPF programs or to how rows are written also need a run on a real host, checked with croft top and croft stats.
Code style
Section titled “Code style”- The smallest code that solves the problem; delete before adding; clear names over comments.
- One module per responsibility; no stage depends on one to its right.
- One source of truth per piece of knowledge; lists that grow go in a JSON file, not in code.
- Comments are rare and one line. Every
unsafeblock has a// SAFETY:comment. Nounwrap()orexpect()in the event path. - Files stay under 500 lines.
Commits
Section titled “Commits”The commit-msg hook checks the first line against Conventional Commits: type(scope): description, lowercase, at most 72 characters, no trailing period. Scopes: collector, labs, apps, research, website; omit for repository-wide changes.
The pre-commit hook runs rustfmt, clippy and the tests when a staged change touches collector/.
This site
Section titled “This site”cd websitenpm installnpm run dev # http://localhost:4321/npm run build # static site in website/distPages are Markdown in website/src/content/docs/; the sidebar follows the folders.