package discovery import ( "errors" "sync" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/tech/sendico/pkg/merrors" ) var ( metricsOnce sync.Once eventLatency *prometheus.HistogramVec eventStatus *prometheus.CounterVec ) func initMetrics() { metricsOnce.Do(func() { eventLatency = promauto.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "sendico", Subsystem: "discovery", Name: "event_latency_seconds", Help: "Latency distribution for discovery event handling.", Buckets: prometheus.DefBuckets, }, []string{"event"}) eventStatus = promauto.NewCounterVec(prometheus.CounterOpts{ Namespace: "sendico", Subsystem: "discovery", Name: "event_requests_total", Help: "Total number of discovery events handled, grouped by event and status.", }, []string{"event", "status"}) }) } func observeEvent(event string, err error, duration time.Duration) { if eventLatency != nil { eventLatency.WithLabelValues(event).Observe(duration.Seconds()) } if eventStatus != nil { eventStatus.WithLabelValues(event, statusLabel(err)).Inc() } } func statusLabel(err error) string { switch { case err == nil: return "ok" case errors.Is(err, merrors.ErrInvalidArg): return "invalid_argument" case errors.Is(err, merrors.ErrNoData): return "not_found" case errors.Is(err, merrors.ErrDataConflict): return "conflict" case errors.Is(err, merrors.ErrAccessDenied): return "denied" case errors.Is(err, merrors.ErrInternal): return "internal" default: return "error" } }