81 lines
2.8 KiB
Go
81 lines
2.8 KiB
Go
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
|
|
}
|
|
}
|