Azure / Azure/unbounded

operator: quiet BootstrapMaintainer per-tick log churn (follow-up to #530)

Open
#533 0 comments 0 reactions 0 assignees View on GitHub
enhancement go
Dominant language
Go
Stars
28
Forks
11
Avg merge
1d 8h
Merged PRs (30d)
55

Description

### Summary

The unbounded-operator's `BootstrapMaintainer` reapplies its owned resources every tick (default 1 minute) and logs each apply at `Info`, producing steady log churn even when nothing changes. Surfaced during review of #530 (PR comment on `internal/operator/namespace.go`).

Per tick the maintainer currently emits ~14 `Info` lines:
- `bootstrap.go` `applyCRDsFromFS`: `"applied CRD"` once per CRD = 12 (`RequiredCRDNames`),
- `bootstrap.go` `bootstrapCRDs`: `"CRDs installed and established"` = 1 (`appliedCount` is always > 0),
- `namespace.go` `BootstrapNamespace`: `"applied system namespace"` = 1 (added in #530).

### Why the obvious fix does not work as-is

Lowering these to `V(1)` does **not** quiet them today. `cmd/unbounded-operator/main.go:143` hard-codes `zap.New(zap.UseDevMode(true))`, and dev mode sets the effective zap level to Debug. controller-runtime maps logr `V(n)` to zap level `-n`, so `V(1)` (level `-1`) is still enabled; only `V(2)+` is suppressed. The existing `internal/operator/migrate.go` `V(1)` "routine" logs (`"ensured secret copied"`, `"reaped legacy component resources"`, etc.) print for the same reason.

### Options

1. **Startup vs maintenance.** Thread a signal through `BootstrapAll` -> `BootstrapNamespace`/`bootstrapCRDs` so the startup call logs applies at `Info` while the `BootstrapMaintainer` tick is quiet (suppress, or use `V(2)` which is suppressed under dev mode). Config-independent; keeps first-install/startup visibility; covers CRDs and namespace.
2. **Make the operator log level configurable.** Bind `zap.Options` flags / default to production `Info` so `V(1)` becomes a real quiet lever operator-wide, then lower routine logs (bootstrap + `migrate.go`) to `V(1)`. Broader: changes default encoder (console -> JSON) and level; affects log parsing/ops. Likely its own PR / a "new default behavior" decision.
3. **Change-aware logging.** Log at `Info` only when an apply actually creates/mutates the object. Cleanest semantics; easy for the namespace (compare the 4 labels), awkward for the 12 CRDs (per-CRD `Get`/resourceVersion compare each tick).

### Acceptance criteria

- [ ] A steady-state `BootstrapMaintainer` tick (nothing changed) produces no per-apply `Info` churn.
- [ ] Startup / first install still logs a clear confirmation at `Info`.
- [ ] The chosen approach is consistent across the namespace and CRD bootstrap paths (and, if the logger is touched, the `migrate.go` routine logs).
- [ ] `make fmt`, `make lint`, `go test ./internal/operator/... ./cmd/unbounded-operator/...` pass.

### References

- #530 (introduced the namespace bootstrap log; review comment raised the churn).
- `internal/operator/bootstrap.go` (`applyCRDsFromFS`, `bootstrapCRDs`), `internal/operator/namespace.go` (`BootstrapNamespace`), `cmd/unbounded-operator/main.go:143` (hard-coded dev-mode logger).

Contributor guide

Open the contributing guide

Research direction

Read internal/operator/bootstrap.go and namespace.go, then inspect cmd/unbounded-operator/main.go:143 and the routine logs in internal/operator/migrate.go. Compare the startup and BootstrapMaintainer paths and choose a consistent way to avoid steady-state per-apply Info churn while retaining startup confirmation. Run make fmt, make lint, and go test ./internal/operator/... ./cmd/unbounded-operator/... to verify the acceptance criteria.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes
Domain
infrastructure, observability
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.