-
Notifications
You must be signed in to change notification settings - Fork 24
/
metrics.go
100 lines (86 loc) · 3.07 KB
/
metrics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package check
import (
"github.com/prometheus/client_golang/prometheus"
flowcontrolv1 "github.com/fluxninja/aperture/api/gen/proto/go/aperture/flowcontrol/check/v1"
"github.com/fluxninja/aperture/pkg/log"
"github.com/fluxninja/aperture/pkg/metrics"
)
// Metrics is used for collecting metrics about Aperture flowcontrol.
type Metrics interface {
// CheckResponse collects metrics about Aperture Check call with DecisionType and Reason.
CheckResponse(
flowcontrolv1.CheckResponse_DecisionType,
flowcontrolv1.CheckResponse_RejectReason,
)
}
// NopMetrics is a no-op implementation of Metrics.
type NopMetrics struct{}
// Ensure NopMetrics implements Metrics interface.
var _ Metrics = NopMetrics{}
// CheckResponse is no-op method for NopMetrics.
func (NopMetrics) CheckResponse(
flowcontrolv1.CheckResponse_DecisionType,
flowcontrolv1.CheckResponse_RejectReason,
) {
}
// PrometheusMetrics stores collected metrics.
type PrometheusMetrics struct {
registry *prometheus.Registry
// Flow control service metrics
// TODO: 3 gauges for 3 types of flowcontrol decisions
checkReceivedTotal prometheus.Counter
checkDecision prometheus.CounterVec
rejectReason prometheus.CounterVec
}
// Ensure PrometheusMetrics implements Metrics interface.
var _ Metrics = &PrometheusMetrics{}
func (pm *PrometheusMetrics) allMetrics() []prometheus.Collector {
return []prometheus.Collector{
pm.checkReceivedTotal,
pm.checkDecision,
pm.rejectReason,
}
}
// NewPrometheusMetrics creates a Prometheus metrics collector.
func NewPrometheusMetrics(registry *prometheus.Registry) (*PrometheusMetrics, error) {
pm := &PrometheusMetrics{
registry: registry,
checkReceivedTotal: prometheus.NewCounter(
prometheus.CounterOpts{
Name: metrics.FlowControlRequestsMetricName,
Help: "Total number of aperture check requests handled",
},
),
checkDecision: *prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: metrics.FlowControlDecisionsMetricName,
Help: "Number of aperture check decisions",
}, []string{metrics.FlowControlCheckDecisionTypeLabel},
),
rejectReason: *prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: metrics.FlowControlRejectReasonsMetricName,
Help: "Number of reject reasons other than unspecified",
}, []string{metrics.FlowControlCheckRejectReasonLabel},
),
}
for _, m := range pm.allMetrics() {
err := pm.registry.Register(m)
if err != nil {
log.Warn().Err(err).Msg("Unable to register metric")
return nil, err
}
}
return pm, nil
}
// CheckResponse collects metrics about Aperture Check call with DecisionType, RejectReason, Error.
func (pm *PrometheusMetrics) CheckResponse(
decision flowcontrolv1.CheckResponse_DecisionType,
rejectReason flowcontrolv1.CheckResponse_RejectReason,
) {
pm.checkReceivedTotal.Inc()
pm.checkDecision.With(prometheus.Labels{metrics.FlowControlCheckDecisionTypeLabel: decision.Enum().String()}).Inc()
if rejectReason != flowcontrolv1.CheckResponse_REJECT_REASON_NONE {
pm.rejectReason.With(prometheus.Labels{metrics.FlowControlCheckRejectReasonLabel: rejectReason.Enum().String()}).Inc()
}
}