Files
egress-proxies-operator/docs/plans/2026-08-11-1742-gcp-provider-verbose-logging.md

4.3 KiB

Plan: Verbose (V-level) logging in the GCP provider

Created: 2026-08-11 17:42

Context

Debugging GCP provisioning is currently blind: the operator has zero .V(n) calls anywhere, so --zap-log-level=debug (or any numeric level) reveals nothing about what the GCP provider is doing — which API calls it makes, with what parameters, and what came back. The goal: with debug/V-level logging enabled, see the details of every GCP Compute API call (Insert/Get/Delete/AggregatedList) including a summary of the response; with default info level, the provider stays as quiet as today.

Approach (the "how")

Logger source — context-carried, not injected. Provider methods all take ctx, and the reconciler already builds a per-request logger (logf.FromContext(ctx) in internal/controller/proxy_controller.go:117) that carries the proxy's name/namespace. The GCP provider will do log := logf.FromContext(ctx).WithName("gcp").WithValues("provider", p.name) at the top of each public method. Zero wiring changes (no registry/constructor/struct changes), and every provider log line automatically inherits the reconcile context (which Proxy triggered it). Calls from the GC sweeper inherit its orphan-gc logger name the same way.

Verbosity scheme (logr convention: .Info() = V(0), debug flag = V(1)):

  • V(1) — one line per GCP API call, after it returns: operation, identifying params, outcome. Examples:
    • Create: "GCP insert instance" with zone, name, machineType, image, opName (currently discarded at gcp.go:117 — capture it, it's the only handle for correlating with GCP's operation log), plus a line for the 409-already-exists path.
    • Get: "GCP get instance" with zone, name, status, mapped state, ip.
    • Delete: "GCP delete instance" with zone, name, opName, and the 404-treated-as-success path.
    • ListByTag: "GCP aggregated list" with filter, count.
    • Error paths at V(1) too: log the raw classification (HTTP status / reason from googleapi.Error) before it's wrapped, since the wrapped error the reconciler sees is coarser.
  • V(2) — request/response detail: full curated insert-request summary (network, networkTag, diskSizeGB, port, labels, cloudInitBytes = len), per-instance lines in ListByTag (id, state, uid, age).

Curated fields, never raw proto dumps. CreateRequest.CloudInit is resolved user-data possibly sourced from a Secret, and it lands in the insert request's metadata — so logging the request proto wholesale would leak it. Log named safe fields only; for cloud-init, log only its byte length. This is a hard rule, and a test asserts it.

Where the calls live: the Provider methods in internal/provider/gcp/gcp.go (Create/Get/Delete/ListByTag), not in realInstances (deliberately untested by design, gcp.go:86) and not an HTTP round-tripper (would log auth headers/user-data, unredactable). The instancesAPI fake seam (newWithAPI, gcp.go:96) keeps everything testable. To surface opName, change Provider.Create/Delete to capture the string their instancesAPI calls already return instead of discarding it.

Files to change

  • internal/provider/gcp/gcp.go — add logf import; V(1)/V(2) logging in Create, Get, Delete, ListByTag; capture opNames. Only file with production changes.
  • internal/provider/gcp/gcp_test.go — new table-driven test TestLogging_verbosity (name TBD per house Test<Function>_<scenario> style): inject a capturing logger via logf.IntoContext(ctx, funcr.New(...)) (github.com/go-logr/logr/funcr, logr already a direct dep), assert:
    • at V(1): expected message + keys per operation (incl. opName),
    • at V(0): nothing logged,
    • cloud-init content never appears in any log output (grep the captured lines for a sentinel string placed in CloudInit).
  • No changes to provider.Provider interface, registry, cmd/main.go, manifests, or the kubernetes provider (it can copy this pattern later).

Verification

go test -race ./internal/provider/gcp/...
go build ./...

Optional live check: run the manager with --zap-log-level=2 against the GCP project and confirm insert/get lines appear during a Proxy reconcile, and that --zap-log-level=info stays quiet.

Also append a CHANGELOG.md entry per house convention once confirmed working.