Add connection tracking collector

This commit is contained in:
Martin Milata 2020-03-06 22:08:00 +01:00
parent d3285ba301
commit 554b72fa88
6 changed files with 113 additions and 30 deletions

View File

@ -175,6 +175,13 @@ func WithIpsec() Option {
}
}
// WithConntrack enables firewall/NAT connection tracking metrics
func WithConntrack() Option {
return func(c *collector) {
c.collectors = append(c.collectors, newConntrackCollector())
}
}
// Option applies options to collector
type Option func(*collector)

View File

@ -0,0 +1,68 @@
package collector
import (
"strconv"
"strings"
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
"gopkg.in/routeros.v2/proto"
)
type conntrackCollector struct {
props []string
totalEntriesDesc *prometheus.Desc
maxEntriesDesc *prometheus.Desc
}
func newConntrackCollector() routerOSCollector {
const prefix = "conntrack"
labelNames := []string{"name", "address"}
return &conntrackCollector{
props: []string{"total-entries", "max-entries"},
totalEntriesDesc: description(prefix, "entries", "Number of tracked connections", labelNames),
maxEntriesDesc: description(prefix, "max_entries", "Conntrack table capacity", labelNames),
}
}
func (c *conntrackCollector) describe(ch chan<- *prometheus.Desc) {
ch <- c.totalEntriesDesc
ch <- c.maxEntriesDesc
}
func (c *conntrackCollector) collect(ctx *collectorContext) error {
reply, err := ctx.client.Run("/ip/firewall/connection/tracking/print", "=.proplist="+strings.Join(c.props, ","))
if err != nil {
log.WithFields(log.Fields{
"device": ctx.device.Name,
"error": err,
}).Error("error fetching conntrack table metrics")
return err
}
for _, re := range reply.Re {
c.collectMetricForProperty("total-entries", c.totalEntriesDesc, re, ctx)
c.collectMetricForProperty("max-entries", c.maxEntriesDesc, re, ctx)
}
return nil
}
func (c *conntrackCollector) collectMetricForProperty(property string, desc *prometheus.Desc, re *proto.Sentence, ctx *collectorContext) {
if re.Map[property] == "" {
return
}
v, err := strconv.ParseFloat(re.Map[property], 64)
if err != nil {
log.WithFields(log.Fields{
"device": ctx.device.Name,
"property": property,
"value": re.Map[property],
"error": err,
}).Error("error parsing conntrack metric value")
return
}
ctx.ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, ctx.device.Name, ctx.device.Address)
}

View File

@ -12,6 +12,7 @@ type Config struct {
Devices []Device `yaml:"devices"`
Features struct {
BGP bool `yaml:"bgp,omitempty"`
Conntrack bool `yaml:"conntrack,omitempty"`
DHCP bool `yaml:"dhcp,omitempty"`
DHCPL bool `yaml:"dhcpl,omitempty"`
DHCPv6 bool `yaml:"dhcpv6,omitempty"`

View File

@ -10,6 +10,7 @@ devices:
features:
bgp: true
conntrack: true
dhcp: true
dhcpv6: true
dhcpl: true

View File

@ -20,6 +20,7 @@ func TestShouldParse(t *testing.T) {
assertDevice("test1", "192.168.1.1", "foo", "bar", c.Devices[0], t)
assertDevice("test2", "192.168.2.1", "test", "123", c.Devices[1], t)
assertFeature("BGP", c.Features.BGP, t)
assertFeature("Conntrack", c.Features.Conntrack, t)
assertFeature("DHCP", c.Features.DHCP, t)
assertFeature("DHCPv6", c.Features.DHCPv6, t)
assertFeature("Pools", c.Features.Pools, t)

View File

@ -37,6 +37,7 @@ var (
ver = flag.Bool("version", false, "find the version of binary")
withBgp = flag.Bool("with-bgp", false, "retrieves BGP routing infrormation")
withConntrack = flag.Bool("with-conntrack", false, "retrieves connection tracking metrics")
withRoutes = flag.Bool("with-routes", false, "retrieves routing table information")
withDHCP = flag.Bool("with-dhcp", false, "retrieves DHCP server metrics")
withDHCPL = flag.Bool("with-dhcpl", false, "retrieves DHCP server lease metrics")
@ -241,6 +242,10 @@ func collectorOptions() []collector.Option {
opts = append(opts, collector.WithIpsec())
}
if *withConntrack || cfg.Features.Conntrack {
opts = append(opts, collector.WithConntrack())
}
if *timeout != collector.DefaultTimeout {
opts = append(opts, collector.WithTimeout(*timeout))
}