# Execution: Trace every libvirt call in the KVM provider Plan: [2026-09-10-0805-kvm-libvirt-tracing.md](../plans/2026-09-10-0805-kvm-libvirt-tracing.md) - [x] Step 0 — Save plan - [x] Step 1 — `errors.go`: shared error fields - [x] Step 2 — `trace.go`: the `tracingAPI` decorator - [x] Step 3 — `conn.go`: pool logging and wrapping - [x] Step 4 — Call sites - [x] Step 5 — Integration test output - [x] Step 6 — Unit tests - [ ] Step 7 — Docs, execution log, CHANGELOG (docs and this log done; CHANGELOG waits for the live run) ## Steps 1–6 — Tracer, pool logging, tests, integration wiring Done as one commit on `feat/kvm-provider`; the plan's assumption that this belongs on the KVM branch rather than its own feature branch was accepted at plan approval. The code follows the plan closely. Things that came out differently or are worth knowing: - **Logger names join with `/` in funcr, `.` in zap.** The trace lines are `kvm/libvirt` in the unit-test capture and in `testr` output, and `kvm.libvirt` under the operator's zap logger. The docs use the zap spelling; the unit test asserts the funcr one. First run of the tier test failed on exactly this. - **Cancel is not reported as a transport error.** The original `call` dropped the connection twice on cancellation (once from the abort closure, once from the "not a libvirt error" branch, harmlessly, since drop is idempotent). With a log line on each drop that would have printed both `context cancelled` and `transport error` for one event, so the transport branch now skips `ctx.Err()`. Covered by `TestHostPool_call_logsDropReason`. - **`ConnectListAllDomains` in the fake includes every defined domain**, so the trace test's fixture (one running managed domain plus one stopped domain for `DomainCreate` to start) lists two; the V(2) assertion checks for the `names` key rather than an exact list. - **`libvirtErrorFields` also feeds `logAPIError`**, which therefore gains `libvirtCodeName` (e.g. `ErrNoDomain`) next to the numeric code. - The seam-coverage guard (`reflect` count of `libvirtAPI` methods vs the test table) is the only thing standing between a future 18th RPC and a silently untraced call; keep it. Verification run before committing: ```bash go build ./... && go vet ./... && go vet -tags=integration ./internal/provider/kvm/ go test -short ./... go test -race -count=1 -cover ./internal/provider/kvm/ # 90.2 %, up from 88.2 go test -tags=integration -count=1 -run TestKVM ./internal/provider/kvm/ # self-skips without env ``` Worth noting: the live run (`make test-integration-kvm` against beelink) had not happened when this was written; it is what Step 7 of the KVM provider plan is waiting on, and its output is the acceptance test for this feature. Expected shape is in the plan's Verification section.