Skip to content

Commit 75194e8

Browse files
authored
refactor metrics registration (#401)
1 parent ca8368a commit 75194e8

File tree

5 files changed

+225
-209
lines changed

5 files changed

+225
-209
lines changed

cmd/root.go

Lines changed: 5 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,15 @@ import (
1212
"slices"
1313
"strings"
1414
"syscall"
15-
"time"
1615

1716
"github.com/prometheus/client_golang/prometheus"
1817
"github.com/prometheus/client_golang/prometheus/promhttp"
19-
io_prometheus_client "github.com/prometheus/client_model/go"
2018
log "github.com/sirupsen/logrus"
2119
"golang.org/x/sync/errgroup"
2220

2321
csbouncer "github.com/crowdsecurity/go-cs-bouncer"
2422
"github.com/crowdsecurity/go-cs-lib/csdaemon"
2523
"github.com/crowdsecurity/go-cs-lib/csstring"
26-
"github.com/crowdsecurity/go-cs-lib/ptr"
2724
"github.com/crowdsecurity/go-cs-lib/version"
2825

2926
"github.com/crowdsecurity/crowdsec/pkg/models"
@@ -35,10 +32,6 @@ import (
3532

3633
const bouncerType = "crowdsec-firewall-bouncer"
3734

38-
type metricsHandler struct {
39-
backend *backend.BackendCTX
40-
}
41-
4235
func backendCleanup(backend *backend.BackendCTX) {
4336
log.Info("Shutting down backend")
4437

@@ -143,140 +136,6 @@ func addDecisions(backend *backend.BackendCTX, decisions []*models.Decision, con
143136
}
144137
}
145138

146-
func getLabelValue(labels []*io_prometheus_client.LabelPair, key string) string {
147-
148-
for _, label := range labels {
149-
if label.GetName() == key {
150-
return label.GetValue()
151-
}
152-
}
153-
154-
return ""
155-
}
156-
157-
// metricsUpdater receives a metrics struct with basic data and populates it with the current metrics.
158-
func (m metricsHandler) metricsUpdater(met *models.RemediationComponentsMetrics, updateInterval time.Duration) {
159-
log.Debugf("Updating metrics")
160-
161-
m.backend.CollectMetrics()
162-
163-
//Most of the common fields are set automatically by the metrics provider
164-
//We only need to care about the metrics themselves
165-
166-
promMetrics, err := prometheus.DefaultGatherer.Gather()
167-
168-
if err != nil {
169-
log.Errorf("unable to gather prometheus metrics: %s", err)
170-
return
171-
}
172-
173-
met.Metrics = append(met.Metrics, &models.DetailedMetrics{
174-
Meta: &models.MetricsMeta{
175-
UtcNowTimestamp: ptr.Of(time.Now().Unix()),
176-
WindowSizeSeconds: ptr.Of(int64(updateInterval.Seconds())),
177-
},
178-
Items: make([]*models.MetricsDetailItem, 0),
179-
})
180-
181-
for _, metricFamily := range promMetrics {
182-
for _, metric := range metricFamily.GetMetric() {
183-
switch metricFamily.GetName() {
184-
case metrics.ActiveBannedIPsMetricName:
185-
//We send the absolute value, as it makes no sense to try to sum them crowdsec side
186-
labels := metric.GetLabel()
187-
value := metric.GetGauge().GetValue()
188-
origin := getLabelValue(labels, "origin")
189-
ipType := getLabelValue(labels, "ip_type")
190-
log.Debugf("Sending active decisions for %s %s | current value: %f", origin, ipType, value)
191-
met.Metrics[0].Items = append(met.Metrics[0].Items, &models.MetricsDetailItem{
192-
Name: ptr.Of("active_decisions"),
193-
Value: ptr.Of(value),
194-
Labels: map[string]string{
195-
"origin": origin,
196-
"ip_type": ipType,
197-
},
198-
Unit: ptr.Of("ip"),
199-
})
200-
case metrics.DroppedBytesMetricName:
201-
labels := metric.GetLabel()
202-
value := metric.GetGauge().GetValue()
203-
origin := getLabelValue(labels, "origin")
204-
ipType := getLabelValue(labels, "ip_type")
205-
key := origin + ipType
206-
// The firewall counter may have been reset since laste collection.
207-
// In this case, don't register a negative value.
208-
newValue := max(0, value-metrics.LastDroppedBytesValue[key])
209-
log.Debugf("Sending dropped bytes for %s %s %f | current value: %f | previous value: %f\n", origin, ipType, newValue, value, metrics.LastDroppedBytesValue[key])
210-
met.Metrics[0].Items = append(met.Metrics[0].Items, &models.MetricsDetailItem{
211-
Name: ptr.Of("dropped"),
212-
Value: &newValue,
213-
Labels: map[string]string{
214-
"origin": origin,
215-
"ip_type": ipType,
216-
},
217-
Unit: ptr.Of("byte"),
218-
})
219-
metrics.LastDroppedBytesValue[key] = value
220-
case metrics.DroppedPacketsMetricName:
221-
labels := metric.GetLabel()
222-
value := metric.GetGauge().GetValue()
223-
origin := getLabelValue(labels, "origin")
224-
ipType := getLabelValue(labels, "ip_type")
225-
key := origin + ipType
226-
newValue := max(0, value-metrics.LastDroppedPacketsValue[key])
227-
log.Debugf("Sending dropped packets for %s %s %f | current value: %f | previous value: %f\n", origin, ipType, newValue, value, metrics.LastDroppedPacketsValue[key])
228-
met.Metrics[0].Items = append(met.Metrics[0].Items, &models.MetricsDetailItem{
229-
Name: ptr.Of("dropped"),
230-
Value: &newValue,
231-
Labels: map[string]string{
232-
"origin": origin,
233-
"ip_type": ipType,
234-
},
235-
Unit: ptr.Of("packet"),
236-
})
237-
metrics.LastDroppedPacketsValue[key] = value
238-
case metrics.ProcessedBytesMetricName:
239-
labels := metric.GetLabel()
240-
value := metric.GetGauge().GetValue()
241-
ipType := getLabelValue(labels, "ip_type")
242-
newValue := max(0, value-metrics.LastProcessedBytesValue[ipType])
243-
log.Debugf("Sending processed bytes for %s %f | current value: %f | previous value: %f\n", ipType, newValue, value, metrics.LastProcessedBytesValue[ipType])
244-
met.Metrics[0].Items = append(met.Metrics[0].Items, &models.MetricsDetailItem{
245-
Name: ptr.Of("processed"),
246-
Value: &newValue,
247-
Labels: map[string]string{
248-
"ip_type": ipType,
249-
},
250-
Unit: ptr.Of("byte"),
251-
})
252-
metrics.LastProcessedBytesValue[ipType] = value
253-
case metrics.ProcessedPacketsMetricName:
254-
labels := metric.GetLabel()
255-
value := metric.GetGauge().GetValue()
256-
ipType := getLabelValue(labels, "ip_type")
257-
newValue := max(0, value-metrics.LastProcessedPacketsValue[ipType])
258-
log.Debugf("Sending processed packets for %s %f | current value: %f | previous value: %f\n", ipType, newValue, value, metrics.LastProcessedPacketsValue[ipType])
259-
met.Metrics[0].Items = append(met.Metrics[0].Items, &models.MetricsDetailItem{
260-
Name: ptr.Of("processed"),
261-
Value: &newValue,
262-
Labels: map[string]string{
263-
"ip_type": ipType,
264-
},
265-
Unit: ptr.Of("packet"),
266-
})
267-
metrics.LastProcessedPacketsValue[ipType] = value
268-
}
269-
}
270-
}
271-
}
272-
273-
func (m metricsHandler) computeMetricsHandler(next http.Handler) http.Handler {
274-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
275-
m.backend.CollectMetrics()
276-
next.ServeHTTP(w, r)
277-
})
278-
}
279-
280139
func Execute() error {
281140
configPath := flag.String("c", "", "path to crowdsec-firewall-bouncer.yaml")
282141
verbose := flag.Bool("v", false, "set verbose mode")
@@ -358,11 +217,11 @@ func Execute() error {
358217
return errors.New("bouncer stream halted")
359218
})
360219

361-
mHandler := metricsHandler{
362-
backend: backend,
220+
mHandler := metrics.Handler{
221+
Backend: backend,
363222
}
364223

365-
metricsProvider, err := csbouncer.NewMetricsProvider(bouncer.APIClient, bouncerType, mHandler.metricsUpdater, log.StandardLogger())
224+
metricsProvider, err := csbouncer.NewMetricsProvider(bouncer.APIClient, bouncerType, mHandler.MetricsUpdater, log.StandardLogger())
366225
if err != nil {
367226
return fmt.Errorf("unable to create metrics provider: %w", err)
368227
}
@@ -372,13 +231,13 @@ func Execute() error {
372231
})
373232

374233
if config.Mode == cfg.IptablesMode || config.Mode == cfg.NftablesMode || config.Mode == cfg.IpsetMode || config.Mode == cfg.PfMode {
375-
prometheus.MustRegister(metrics.TotalDroppedBytes, metrics.TotalDroppedPackets, metrics.TotalActiveBannedIPs, metrics.TotalProcessedBytes, metrics.TotalProcessedPackets)
234+
metrics.Map.MustRegisterAll()
376235
}
377236

378237
prometheus.MustRegister(csbouncer.TotalLAPICalls, csbouncer.TotalLAPIError)
379238
if config.PrometheusConfig.Enabled {
380239
go func() {
381-
http.Handle("/metrics", mHandler.computeMetricsHandler(promhttp.Handler()))
240+
http.Handle("/metrics", mHandler.ComputeMetricsHandler(promhttp.Handler()))
382241

383242
listenOn := net.JoinHostPort(
384243
config.PrometheusConfig.ListenAddress,

pkg/iptables/metrics.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -254,44 +254,44 @@ func (ctx *ipTablesContext) collectMetrics() (map[string]int, map[string]int, in
254254
func (ipt *iptables) CollectMetrics() {
255255
if ipt.v4 != nil {
256256
for origin, set := range ipt.v4.ipsets {
257-
metrics.TotalActiveBannedIPs.With(prometheus.Labels{"ip_type": "ipv4", "origin": origin}).Set(float64(set.Len()))
257+
metrics.Map[metrics.ActiveBannedIPs].Gauge.With(prometheus.Labels{"ip_type": "ipv4", "origin": origin}).Set(float64(set.Len()))
258258
}
259259
ipv4DroppedPackets, ipv4DroppedBytes, ipv4ProcessedPackets, ipv4ProcessedBytes, err := ipt.v4.collectMetrics()
260260

261261
if err != nil {
262262
log.Errorf("can't collect dropped packets for ipv4 from iptables: %s", err)
263263
} else {
264-
metrics.TotalProcessedPackets.With(prometheus.Labels{"ip_type": "ipv4"}).Set(float64(ipv4ProcessedPackets))
265-
metrics.TotalProcessedBytes.With(prometheus.Labels{"ip_type": "ipv4"}).Set(float64(ipv4ProcessedBytes))
264+
metrics.Map[metrics.ProcessedPackets].Gauge.With(prometheus.Labels{"ip_type": "ipv4"}).Set(float64(ipv4ProcessedPackets))
265+
metrics.Map[metrics.ProcessedBytes].Gauge.With(prometheus.Labels{"ip_type": "ipv4"}).Set(float64(ipv4ProcessedBytes))
266266

267267
for origin, count := range ipv4DroppedPackets {
268-
metrics.TotalDroppedPackets.With(prometheus.Labels{"ip_type": "ipv4", "origin": origin}).Set(float64(count))
268+
metrics.Map[metrics.DroppedPackets].Gauge.With(prometheus.Labels{"ip_type": "ipv4", "origin": origin}).Set(float64(count))
269269
}
270270

271271
for origin, count := range ipv4DroppedBytes {
272-
metrics.TotalDroppedBytes.With(prometheus.Labels{"ip_type": "ipv4", "origin": origin}).Set(float64(count))
272+
metrics.Map[metrics.DroppedBytes].Gauge.With(prometheus.Labels{"ip_type": "ipv4", "origin": origin}).Set(float64(count))
273273
}
274274
}
275275
}
276276

277277
if ipt.v6 != nil {
278278
for origin, set := range ipt.v6.ipsets {
279-
metrics.TotalActiveBannedIPs.With(prometheus.Labels{"ip_type": "ipv6", "origin": origin}).Set(float64(set.Len()))
279+
metrics.Map[metrics.ActiveBannedIPs].Gauge.With(prometheus.Labels{"ip_type": "ipv6", "origin": origin}).Set(float64(set.Len()))
280280
}
281281
ipv6DroppedPackets, ipv6DroppedBytes, ipv6ProcessedPackets, ipv6ProcessedBytes, err := ipt.v6.collectMetrics()
282282

283283
if err != nil {
284284
log.Errorf("can't collect dropped packets for ipv6 from iptables: %s", err)
285285
} else {
286-
metrics.TotalProcessedPackets.With(prometheus.Labels{"ip_type": "ipv6"}).Set(float64(ipv6ProcessedPackets))
287-
metrics.TotalProcessedBytes.With(prometheus.Labels{"ip_type": "ipv6"}).Set(float64(ipv6ProcessedBytes))
286+
metrics.Map[metrics.ProcessedPackets].Gauge.With(prometheus.Labels{"ip_type": "ipv6"}).Set(float64(ipv6ProcessedPackets))
287+
metrics.Map[metrics.ProcessedBytes].Gauge.With(prometheus.Labels{"ip_type": "ipv6"}).Set(float64(ipv6ProcessedBytes))
288288

289289
for origin, count := range ipv6DroppedPackets {
290-
metrics.TotalDroppedPackets.With(prometheus.Labels{"ip_type": "ipv6", "origin": origin}).Set(float64(count))
290+
metrics.Map[metrics.DroppedPackets].Gauge.With(prometheus.Labels{"ip_type": "ipv6", "origin": origin}).Set(float64(count))
291291
}
292292

293293
for origin, count := range ipv6DroppedBytes {
294-
metrics.TotalDroppedBytes.With(prometheus.Labels{"ip_type": "ipv6", "origin": origin}).Set(float64(count))
294+
metrics.Map[metrics.DroppedBytes].Gauge.With(prometheus.Labels{"ip_type": "ipv6", "origin": origin}).Set(float64(count))
295295
}
296296
}
297297
}

0 commit comments

Comments
 (0)