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

@@ -41,6 +41,7 @@ import (
crawlv1alpha1 "gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/api/v1alpha1"
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/health"
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/provider"
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/tracing"
)
// HealthSnapshotter provides the current probe verdict for a proxy. The
@@ -96,9 +97,14 @@ func (r *ProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
}
base := p.DeepCopy()
defer func() {
// Runs inside the root reconcile span (this defer fires before the
// tracing.NewReconciler wrapper sees the return), and its error is
// folded into err, which that wrapper records.
pctx, span := tracing.Start(ctx, "status.patch")
defer span.End()
// NotFound is expected when this reconcile just removed the last
// finalizer and the object is already gone.
if perr := r.patchStatusIfChanged(ctx, base, &p); perr != nil && !apierrors.IsNotFound(perr) {
if perr := r.patchStatusIfChanged(pctx, base, &p); perr != nil && !apierrors.IsNotFound(perr) {
err = errors.Join(err, perr)
}
}()
@@ -114,6 +120,8 @@ func (r *ProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
}
func (r *ProxyReconciler) reconcileManaged(ctx context.Context, p *crawlv1alpha1.Proxy) (ctrl.Result, error) {
ctx, span := tracing.Start(ctx, "reconcile.managed")
defer span.End()
log := logf.FromContext(ctx)
if controllerutil.AddFinalizer(p, crawlv1alpha1.FinalizerName) {
@@ -224,6 +232,8 @@ func (r *ProxyReconciler) reconcileManaged(ctx context.Context, p *crawlv1alpha1
// exists" — hence: delete, poll to NotFound, only then advance the hash and
// let the create branch run.
func (r *ProxyReconciler) replaceInstance(ctx context.Context, p *crawlv1alpha1.Proxy, prov provider.Provider, hash string) (ctrl.Result, error) {
ctx, span := tracing.Start(ctx, "reconcile.replaceInstance")
defer span.End()
_, err := prov.Get(ctx, p.Status.ProviderID)
if provider.Class(err) == provider.ErrNotFound {
// Old instance is gone. The Update inside setSpecHash refreshes p
@@ -252,6 +262,8 @@ func (r *ProxyReconciler) replaceInstance(ctx context.Context, p *crawlv1alpha1.
}
func (r *ProxyReconciler) reconcileDelete(ctx context.Context, p *crawlv1alpha1.Proxy) (ctrl.Result, error) {
ctx, span := tracing.Start(ctx, "reconcile.delete")
defer span.End()
if !controllerutil.ContainsFinalizer(p, crawlv1alpha1.FinalizerName) {
return ctrl.Result{}, nil
}
@@ -409,7 +421,10 @@ func (r *ProxyReconciler) SetupWithManager(mgr ctrl.Manager) error {
if r.HealthEvents != nil {
b = b.WatchesRawSource(source.Channel(r.HealthEvents, &handler.EnqueueRequestForObject{}))
}
return b.Complete(r)
// Root span per reconcile; sub-reconcilers and the status flush hang
// their spans off it. Tests calling r.Reconcile directly bypass the
// wrapper and see no-op spans — the global tracer is never set there.
return b.Complete(tracing.NewReconciler("Proxy", r))
}
func (r *ProxyReconciler) applyDefaults() {