package metrics import ( "errors" "fmt" "github.com/prometheus/client_golang/prometheus" healthDomain "proxy-pool/internal/domain/health" ) // CheckerCollector exposes bounded Checker task-flow counters. The only // labels are the three fixed health levels and accepted/rejected outcome. type CheckerCollector struct { tasksDispatched *prometheus.CounterVec observations *prometheus.CounterVec } var _ healthDomain.TaskMetricsObserver = (*CheckerCollector)(nil) func NewCheckerCollector(registerer prometheus.Registerer) (*CheckerCollector, error) { if registerer == nil { return nil, ErrInvalidDependencies } tasks, err := registerCounterVec(registerer, prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "proxy_pool", Subsystem: "checker", Name: "tasks_dispatched_total", Help: "Number of checker tasks dispatched after a successful task-stream send.", }, []string{"level"})) if err != nil { return nil, err } observations, err := registerCounterVec(registerer, prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "proxy_pool", Subsystem: "checker", Name: "observations_total", Help: "Number of checker observations accepted or rejected after decoding a known level.", }, []string{"level", "result"})) if err != nil { return nil, err } return &CheckerCollector{tasksDispatched: tasks, observations: observations}, nil } func (collector *CheckerCollector) ObserveTaskDispatch(level healthDomain.Level, count int) { if collector == nil || collector.tasksDispatched == nil || count <= 0 || !validCheckerLevel(level) { return } collector.tasksDispatched.WithLabelValues(string(level)).Add(float64(count)) } func (collector *CheckerCollector) ObserveObservation(level healthDomain.Level, result healthDomain.ObservationMetricResult) { if collector == nil || collector.observations == nil || !validCheckerLevel(level) || (result != healthDomain.ObservationMetricAccepted && result != healthDomain.ObservationMetricRejected) { return } collector.observations.WithLabelValues(string(level), string(result)).Inc() } func registerCounterVec(registerer prometheus.Registerer, candidate *prometheus.CounterVec) (*prometheus.CounterVec, error) { if err := registerer.Register(candidate); err == nil { return candidate, nil } else { var registered prometheus.AlreadyRegisteredError if !errors.As(err, ®istered) { return nil, fmt.Errorf("register checker metrics: %w", err) } existing, ok := registered.ExistingCollector.(*prometheus.CounterVec) if !ok { return nil, fmt.Errorf("register checker metrics: existing collector has unexpected type") } return existing, nil } } func validCheckerLevel(level healthDomain.Level) bool { switch level { case healthDomain.LevelBasic, healthDomain.LevelEgress, healthDomain.LevelTarget: return true default: return false } }