53 lines
1.5 KiB
Go
53 lines
1.5 KiB
Go
package tracing
|
|
|
|
import (
|
|
"context"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/codes"
|
|
"go.opentelemetry.io/otel/trace"
|
|
"sigs.k8s.io/controller-runtime/pkg/controller"
|
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
)
|
|
|
|
// NewReconciler wraps inner so every reconcile runs in a root span named
|
|
// "Reconcile <kind>" and every log line under it carries the trace context.
|
|
// Reconciles are triggered by watch events with no incoming trace to
|
|
// continue, so each one starts a new trace.
|
|
func NewReconciler(kind string, inner reconcile.Reconciler, opts ...Option) reconcile.Reconciler {
|
|
return &tracedReconciler{
|
|
spanName: "Reconcile " + kind,
|
|
inner: inner,
|
|
tracer: newOptions(opts).tracer(),
|
|
}
|
|
}
|
|
|
|
type tracedReconciler struct {
|
|
spanName string
|
|
inner reconcile.Reconciler
|
|
tracer trace.Tracer
|
|
}
|
|
|
|
func (t *tracedReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
|
|
ctx, span := StartSpan(ctx, t.tracer, t.spanName,
|
|
trace.WithAttributes(
|
|
attribute.String("k8s.namespace.name", req.Namespace),
|
|
attribute.String("k8s.object.name", req.Name),
|
|
))
|
|
defer span.End()
|
|
if id := controller.ReconcileIDFromContext(ctx); id != "" {
|
|
span.SetAttributes(attribute.String("reconcile.id", string(id)))
|
|
}
|
|
|
|
res, err := t.inner.Reconcile(ctx, req)
|
|
if err != nil {
|
|
span.SetStatus(codes.Error, err.Error())
|
|
return res, err
|
|
}
|
|
span.SetStatus(codes.Ok, "")
|
|
if res.RequeueAfter > 0 {
|
|
span.SetAttributes(attribute.Int64("reconcile.requeue_after_ms", res.RequeueAfter.Milliseconds()))
|
|
}
|
|
return res, nil
|
|
}
|