Manager env block (downward-API resource attrs, commented OTLP examples), architecture §10 + Decisions entries, README section. Lint: goconst constants, gofmt, logcheck (Setup now takes its logger from ctx via logf.FromContext). Co-Authored-By: Claude <noreply@anthropic.com>
75 lines
1.9 KiB
Go
75 lines
1.9 KiB
Go
package provider
|
|
|
|
import "context"
|
|
|
|
// RequestRecorder receives one record per provider API call. Implemented
|
|
// by internal/metrics; defined here so this package needs no metrics
|
|
// dependency.
|
|
type RequestRecorder interface {
|
|
ProviderRequest(provider, op, result string)
|
|
}
|
|
|
|
// WithMetrics wraps a Provider so every call is recorded with its
|
|
// classified result — zero-cost instrumentation for the next five
|
|
// providers, and the one place Class is called purely for observability.
|
|
func WithMetrics(name string, p Provider, rec RequestRecorder) Provider {
|
|
return &instrumented{name: name, inner: p, rec: rec}
|
|
}
|
|
|
|
type instrumented struct {
|
|
name string
|
|
inner Provider
|
|
rec RequestRecorder
|
|
}
|
|
|
|
func (i *instrumented) Create(ctx context.Context, req CreateRequest) (string, error) {
|
|
id, err := i.inner.Create(ctx, req)
|
|
i.record("create", err)
|
|
return id, err
|
|
}
|
|
|
|
func (i *instrumented) Get(ctx context.Context, providerID string) (*Instance, error) {
|
|
inst, err := i.inner.Get(ctx, providerID)
|
|
i.record("get", err)
|
|
return inst, err
|
|
}
|
|
|
|
func (i *instrumented) Delete(ctx context.Context, providerID string) error {
|
|
err := i.inner.Delete(ctx, providerID)
|
|
i.record("delete", err)
|
|
return err
|
|
}
|
|
|
|
func (i *instrumented) ListByTag(ctx context.Context) ([]Instance, error) {
|
|
instances, err := i.inner.ListByTag(ctx)
|
|
i.record("list", err)
|
|
return instances, err
|
|
}
|
|
|
|
func (i *instrumented) record(op string, err error) {
|
|
i.rec.ProviderRequest(i.name, op, resultLabel(err))
|
|
}
|
|
|
|
const (
|
|
resultOK = "ok"
|
|
resultNotFound = "not_found"
|
|
resultQuotaExceeded = "quota_exceeded"
|
|
resultPermanent = "permanent"
|
|
resultTransient = "transient"
|
|
)
|
|
|
|
func resultLabel(err error) string {
|
|
switch Class(err) {
|
|
case nil:
|
|
return resultOK
|
|
case ErrNotFound:
|
|
return resultNotFound
|
|
case ErrQuotaExceeded:
|
|
return resultQuotaExceeded
|
|
case ErrPermanent:
|
|
return resultPermanent
|
|
default:
|
|
return resultTransient
|
|
}
|
|
}
|