Trace reconciles: root span wrapper plus state-machine sub-spans

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-24 10:53:52 +02:00
parent 8e4f3b9b13
commit 896bf89a19
2 changed files with 36 additions and 3 deletions

View File

@@ -6,7 +6,7 @@ Plan: `docs/plans/2026-08-24-1025-otel-tracing.md`
- [x] Step 2 — New package `internal/tracing`
- [x] Step 3 — `provider.WithTracing` decorator
- [x] Step 4 — `cmd/main.go` wiring
- [ ] Step 5 — Reconciler spans
- [x] Step 5 — Reconciler spans
- [ ] Step 6 — Discovery server
- [ ] Step 7 — GC + health
- [ ] Step 8 — GCP wire-log enrichment
@@ -100,3 +100,21 @@ gcp constructor already used for wire-log options.
Deviation: the plan put `--trace-health-probes` here, but the flag needs the
`health.Engine.TraceProbes` field that Step 7 introduces — moved there to
keep every commit compiling.
## Step 5 — Reconciler spans
`SetupWithManager` completes with `tracing.NewReconciler("Proxy", r)`;
sub-spans `reconcile.managed` / `reconcile.replaceInstance` /
`reconcile.delete` open at the top of each state machine, and `status.patch`
opens inside the deferred flush closure so it stays within the root span
while its error still folds into the recorded result. `reconcileExternal`
left unspanned as planned (no I/O).
Two small judgment calls: the sub-spans carry no extra attributes — the
provider decorator already records `provider.id`, and the root span carries
the object identity, so duplicating them was noise; and `status.patch` is
emitted every reconcile even when nothing changed (the no-op compare is the
span's content — a real PATCH shows up as its k8s HTTP child). Tests that
call `r.Reconcile` directly bypass the wrapper; with no global tracer set
they see no-op spans, so the existing fake-client and envtest suites run
unchanged.