A prometheus exporter that exposes nftables counters
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.4 KiB

package main
import (
"log"
"net/http"
"strings"
"time"
"github.com/google/nftables"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var conn nftables.Conn
type nftablesCollector struct {
ipv4Traffic *prometheus.Desc
ipv6Traffic *prometheus.Desc
}
func newNftablesCollector() *nftablesCollector {
return &nftablesCollector{
ipv4Traffic: prometheus.NewDesc("ipv4_traffic_bytes_counter",
"Count how many bytes of IPv4 traffic this router has seen.",
[]string{"direction"}, nil,
),
ipv6Traffic: prometheus.NewDesc("ipv6_traffic_bytes_counter",
"Count how many bytes of IPv6 traffic this router has seen.",
[]string{"direction"}, nil,
),
}
}
func (collector *nftablesCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- collector.ipv4Traffic
ch <- collector.ipv6Traffic
}
func (collector *nftablesCollector) Collect(ch chan<- prometheus.Metric) {
var table nftables.Table = nftables.Table{Name: "ip-counter", Family: nftables.TableFamilyINet}
objects, err := conn.GetObjects(&table)
if err != nil {
log.Println(err)
return
}
matches := 0
for i := range objects {
counter, ok := objects[i].(*nftables.CounterObj)
if !ok {
// not a counter
continue
}
parts := strings.Split(counter.Name, "-")
var desc *prometheus.Desc
if parts[0] == "IPv4" {
desc = collector.ipv4Traffic
} else if parts[0] == "IPv6" {
desc = collector.ipv6Traffic
} else {
continue
}
var direction string
if parts[1] == "In" {
direction = "incoming"
} else if parts[1] == "Out" {
direction = "outgoing"
} else {
continue
}
matches++
bytes := prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(counter.Bytes), direction)
ch <- bytes
}
if matches == 0 {
log.Println("Collect: no object matched")
}
}
func main() {
tables, err := conn.ListTables()
if err != nil {
log.Fatal(err)
}
if len(tables) == 0 {
log.Fatal("nftables: no table to show!")
}
registry := prometheus.NewPedanticRegistry()
nftc := newNftablesCollector()
registry.MustRegister(nftc)
var opts promhttp.HandlerOpts
opts.ErrorLog = log.Default()
opts.ErrorHandling = promhttp.HTTPErrorOnError
opts.MaxRequestsInFlight = 5
opts.Timeout = 5 * time.Second
opts.EnableOpenMetrics = true
http.Handle("/metrics", promhttp.HandlerFor(registry, opts))
log.Fatal(http.ListenAndServe(":9101", nil))
}