# Execution: Verbose (V-level) logging in the GCP provider Plan: `docs/plans/2026-08-11-1742-gcp-provider-verbose-logging.md` - [x] Step 0 — Save and commit the plan - [x] Step 1 — V(1)/V(2) logging in `internal/provider/gcp` (gcp.go, errors.go) - [x] Step 2 — Tests (verbosity tiers, error detail, cloud-init leak guard) - [ ] Step 3 — CHANGELOG entry (after the user confirms it works live) ## Step 1 — logging in the provider Went as planned: context-carried logger (`logf.FromContext(ctx).WithName("gcp")`), V(1) one line per API call, V(2) request/list detail, opNames captured from the `instancesAPI` seam instead of being discarded. `logAPIError` lives in `errors.go` (next to `classify`, whose imports it shares) rather than `gcp.go` as loosely implied by the plan — same package, so no behavioural difference. These are the first `.V(n)` calls and the first logging import anywhere under `internal/provider/`. Worth noting: the gopls `errorsastype` suggestion fired on the new `errors.As` in `logAPIError` (Go's newer `errors.AsType`); kept `errors.As` for consistency with the three existing uses in the same file. Same for the `newexpr` (`proto.String` → `new`) suggestions — the codebase consistently uses `proto.String`. ## Step 2 — tests `funcr.New` as the capturing sink, injected via `logr.NewContext`, exactly the seam the plan predicted. One deviation: instead of a single `TestLogging_verbosity` table, it split into three tests — `_verbosityTiers` (table over V=0/1/2, incl. the cloud-init sentinel leak assertion), `_apiErrorKeepsHTTPDetail` (403 quotaExceeded keeps `httpStatus`/reason at V(1)), and `_treatedAsSuccessPathsAreExplicit` (409-on-create / 404-on-delete each log their "treated as success" line) — the last two exercise fake error wiring that didn't fit the tier table cleanly. Verified with: ```bash go test -race ./internal/provider/gcp/ go test ./... ```