81 lines
2.5 KiB
Go
81 lines
2.5 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/codes"
|
|
"go.opentelemetry.io/otel/trace"
|
|
|
|
"gitea.home.hrajfrisbee.cz/kacerr/egress-proxies-operator/internal/tracing"
|
|
)
|
|
|
|
// WithTracing wraps a Provider so every call runs in a client span carrying
|
|
// the classified result, mirroring WithMetrics. It goes through
|
|
// tracing.StartSpan, so provider-internal logs (e.g. the gcp provider's
|
|
// context logger) inherit traceID/spanID. Errors pass through unmodified.
|
|
func WithTracing(name string, p Provider, opts ...tracing.Option) Provider {
|
|
return &traced{name: name, inner: p, tracer: tracing.Tracer(opts...)}
|
|
}
|
|
|
|
type traced struct {
|
|
name string
|
|
inner Provider
|
|
tracer trace.Tracer
|
|
}
|
|
|
|
func (t *traced) Create(ctx context.Context, req CreateRequest) (string, error) {
|
|
ctx, span := t.start(ctx, "provider.create")
|
|
id, err := t.inner.Create(ctx, req)
|
|
if id != "" {
|
|
span.SetAttributes(attribute.String("provider.id", id))
|
|
}
|
|
t.end(span, err)
|
|
return id, err
|
|
}
|
|
|
|
func (t *traced) Get(ctx context.Context, providerID string) (*Instance, error) {
|
|
ctx, span := t.start(ctx, "provider.get")
|
|
span.SetAttributes(attribute.String("provider.id", providerID))
|
|
inst, err := t.inner.Get(ctx, providerID)
|
|
t.end(span, err)
|
|
return inst, err
|
|
}
|
|
|
|
func (t *traced) Delete(ctx context.Context, providerID string) error {
|
|
ctx, span := t.start(ctx, "provider.delete")
|
|
span.SetAttributes(attribute.String("provider.id", providerID))
|
|
err := t.inner.Delete(ctx, providerID)
|
|
t.end(span, err)
|
|
return err
|
|
}
|
|
|
|
func (t *traced) ListByTag(ctx context.Context) ([]Instance, error) {
|
|
ctx, span := t.start(ctx, "provider.list")
|
|
instances, err := t.inner.ListByTag(ctx)
|
|
span.SetAttributes(attribute.Int("provider.instances", len(instances)))
|
|
t.end(span, err)
|
|
return instances, err
|
|
}
|
|
|
|
func (t *traced) start(ctx context.Context, op string) (context.Context, trace.Span) {
|
|
return tracing.StartSpan(ctx, t.tracer, op,
|
|
trace.WithSpanKind(trace.SpanKindClient),
|
|
trace.WithAttributes(attribute.String("provider.name", t.name)))
|
|
}
|
|
|
|
// end records the taxonomy class and closes the span. ErrNotFound stays Ok:
|
|
// the reconciler polls Get to NotFound during replacement/deletion, so it is
|
|
// an expected answer, not a failure — same reasoning as resultLabel's
|
|
// distinct "not_found" bucket.
|
|
func (t *traced) end(span trace.Span, err error) {
|
|
span.SetAttributes(attribute.String("provider.result", resultLabel(err)))
|
|
switch Class(err) {
|
|
case nil, ErrNotFound:
|
|
span.SetStatus(codes.Ok, "")
|
|
default:
|
|
span.SetStatus(codes.Error, err.Error())
|
|
}
|
|
span.End()
|
|
}
|