add switch metrics

This commit is contained in:
Alexandre Blazart 2021-02-26 22:33:39 +01:00
parent 8c53875591
commit 0ab7c09f24
3 changed files with 179 additions and 30 deletions

View file

@ -3,6 +3,7 @@ package main
import (
"os"
"strconv"
"strings"
"sync"
"github.com/prometheus/client_golang/prometheus"
@ -32,10 +33,6 @@ var (
metricPrefix+"system_fan_rpm",
"fan rpm",
[]string{"id"}, nil)
promDescConnectionRate = prometheus.NewDesc(
metricPrefix+"connection_rate",
"current upload/download rate in byte/s",
[]string{"dir"}, nil) // up/down. XXX delme?
promDescConnectionBandwith = prometheus.NewDesc(
metricPrefix+"connection_bandwith_bps",
"available upload/download bandwidth in bit/s",
@ -44,6 +41,7 @@ var (
metricPrefix+"connection_bytes",
"total uploaded/downloaded bytes since last connection",
[]string{"dir"}, nil) // up/down
promDescConnectionXdslInfo = prometheus.NewDesc(
metricPrefix+"connection_xdsl_info",
"constant metric with value=0. Various information about the XDSL connection",
@ -68,6 +66,7 @@ var (
metricPrefix+"connection_xdsl_attn_db",
"in Db",
[]string{"dir"}, nil) // up/down
promDescConnectionFtthInfo = prometheus.NewDesc(
metricPrefix+"connection_ftth_info",
"constant metric with value=0. Various information about the FTTH connection",
@ -76,11 +75,29 @@ var (
metricPrefix+"connection_fttp_sfp_pwr_dbm",
"in Dbm",
[]string{"dir"}, nil) // rx/tx
promDescSwitchPortConnected = prometheus.NewDesc(
metricPrefix+"switch_port_connected",
"in bps",
nil, nil)
promDescSwitchPortBandwidth = prometheus.NewDesc(
metricPrefix+"switch_port_bandwidth",
"in bps",
[]string{"id", "link", "duplex"}, nil) // rx/tx
promDescSwitchPortBytes = prometheus.NewDesc(
metricPrefix+"switch_port_bytes",
"total rx/tx bytes",
[]string{"id", "dir", "state"}, nil) // rx/tx, good/bad
promDescSwitchHost = prometheus.NewDesc(
metricPrefix+"switch_host",
"constant metric with value=0. List of MAC addresses connected to the switch",
[]string{"id", "mac", "hostname"}, nil) // rx/tx
)
// Collector is the prometheus collector for the freebox exporter
type Collector struct {
freebox *fbx.FreeboxConnection
listHosts bool
freebox *fbx.FreeboxConnection
}
func (c *Collector) Describe(ch chan<- *prometheus.Desc) {
@ -100,7 +117,7 @@ func (c *Collector) Describe(ch chan<- *prometheus.Desc) {
func (c *Collector) Collect(ch chan<- prometheus.Metric) {
log.Debug.Println("Collect")
wg := sync.WaitGroup{}
wg.Add(2)
wg.Add(3)
var firmwareVersion string
var mac string
@ -110,6 +127,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) {
go func() {
defer wg.Done()
log.Debug.Println("Collect system")
if m, err := c.freebox.GetMetricsSystem(); err == nil {
firmwareVersion = m.FirmwareVersion
mac = m.Mac
@ -145,6 +163,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) {
go func() {
defer wg.Done()
log.Debug.Println("Collect connection")
if m, err := c.freebox.GetMetricsConnection(); err == nil {
cnxType = m.Type
cnxState = m.State
@ -152,8 +171,6 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) {
cnxIPv4 = m.IPv4
cnxIPv6 = m.IPv6
c.collectGauge(ch, m.RateUp, promDescConnectionRate, "up")
c.collectGauge(ch, m.RateDown, promDescConnectionRate, "down")
c.collectGauge(ch, m.BandwidthUp, promDescConnectionBandwith, "up")
c.collectGauge(ch, m.BandwidthDown, promDescConnectionBandwith, "down")
c.collectCounter(ch, m.BytesUp, promDescConnectionBytes, "up")
@ -189,10 +206,49 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) {
}
}()
go func() {
defer wg.Done()
log.Debug.Println("Collect switch")
if m, err := c.freebox.GetMetricsSwitch(); err == nil {
numPortsConnected := 0
for _, port := range m.Ports {
if port.Link == "up" {
numPortsConnected++
}
speed, _ := strconv.Atoi(port.Speed)
portID := strconv.FormatInt(port.ID, 10)
ch <- prometheus.MustNewConstMetric(promDescSwitchPortBandwidth, prometheus.GaugeValue, float64(speed),
portID,
port.Link,
port.Duplex)
if port.Stats != nil {
c.collectCounter(ch, port.Stats.RxGoodBytes, promDescSwitchPortBytes, portID, "rx", "good")
c.collectCounter(ch, port.Stats.RxBadBytes, promDescSwitchPortBytes, portID, "rx", "bad")
c.collectCounter(ch, port.Stats.TxBytes, promDescSwitchPortBytes, portID, "tx", "")
}
if c.listHosts {
for _, mac := range port.MacList {
ch <- prometheus.MustNewConstMetric(promDescSwitchHost, prometheus.GaugeValue, 0,
portID,
strings.ToLower(mac.Mac),
mac.Hostname)
}
}
}
ch <- prometheus.MustNewConstMetric(promDescSwitchPortConnected, prometheus.GaugeValue, float64(numPortsConnected))
} else {
log.Error.Println(err)
}
}()
wg.Wait()
ch <- prometheus.MustNewConstMetric(promDescInfo, prometheus.GaugeValue, 0,
firmwareVersion,
mac,
strings.ToLower(mac),
serial,
boardName,
boxFlavor,
@ -251,8 +307,10 @@ func (c *Collector) toString(b *bool) string {
return ""
}
func NewCollector(debug bool, filename string) *Collector {
result := &Collector{}
func NewCollector(filename string, listHosts, debug bool) *Collector {
result := &Collector{
listHosts: listHosts,
}
newConfig := false
if r, err := os.Open(filename); err == nil {
log.Info.Println("Use configuration file", filename)

View file

@ -1,27 +1,34 @@
package fbx
import (
"fmt"
"sync"
"github.com/trazfr/freebox-exporter/log"
)
// MetricsFreeboxSystem https://dev.freebox.fr/sdk/os/system/
type MetricsFreeboxSystem struct {
FirmwareVersion string `json:"firmware_version"`
Mac string `json:"mac"`
Serial string `json:"serial"`
Uptime string `json:"uptime"`
UptimeValue *int64 `json:"uptime_val"`
BoardName string `json:"board_name"`
TempCPUM *int64 `json:"temp_cpum"` // seems deprecated
TempSW *int64 `json:"temp_sw"` // seems deprecated
TempCPUB *int64 `json:"temp_cpub"` // seems deprecated
FanRpm *int64 `json:"fan_rpm"`
BoxAuthenticated *bool `json:"box_authenticated"`
DiskStatus string `json:"disk_status"`
BoxFlavor string `json:"box_flavor"`
UserMainStorage string `json:"user_main_storage"`
Sensors []MetricsFreeboxSensor `json:"sensors"` // undocumented
Fans []MetricsFreeboxSensor `json:"fans"` // undocumented
FirmwareVersion string `json:"firmware_version"`
Mac string `json:"mac"`
Serial string `json:"serial"`
Uptime string `json:"uptime"`
UptimeValue *int64 `json:"uptime_val"`
BoardName string `json:"board_name"`
TempCPUM *int64 `json:"temp_cpum"` // seems deprecated
TempSW *int64 `json:"temp_sw"` // seems deprecated
TempCPUB *int64 `json:"temp_cpub"` // seems deprecated
FanRpm *int64 `json:"fan_rpm"`
BoxAuthenticated *bool `json:"box_authenticated"`
DiskStatus string `json:"disk_status"`
BoxFlavor string `json:"box_flavor"`
UserMainStorage string `json:"user_main_storage"`
Sensors []MetricsFreeboxSystemSensor `json:"sensors"` // undocumented
Fans []MetricsFreeboxSystemSensor `json:"fans"` // undocumented
}
// MetricsFreeboxSensor undocumented
type MetricsFreeboxSensor struct {
// MetricsFreeboxSystemSensor undocumented
type MetricsFreeboxSystemSensor struct {
ID string `json:"id"`
Name string `json:"name"`
Value *int64 `json:"value"`
@ -101,6 +108,60 @@ type MetricsFreeboxConnectionAll struct {
Ftth *MetricsFreeboxConnectionFtth
}
// MetricsFreeboxSwitch https://dev.freebox.fr/sdk/os/switch/
type MetricsFreeboxSwitch struct {
Ports []*MetricsFreeboxSwitchStatus
}
// MetricsFreeboxSwitchStatus https://dev.freebox.fr/sdk/os/switch/
type MetricsFreeboxSwitchStatus struct {
ID int64 `json:"id"`
Duplex string `json:"duplex"`
Link string `json:"link"`
Mode string `json:"mode"`
Speed string `json:"speed"`
MacList []struct {
Mac string `json:"mac"`
Hostname string `json:"hostname"`
} `json:"mac_list"`
Stats *MetricsFreeboxSwitchPortStats `json:"-"`
}
// MetricsFreeboxSwitchPortStats https://dev.freebox.fr/sdk/os/switch/#switch-port-stats-object-unstable
type MetricsFreeboxSwitchPortStats struct {
RxBadBytes *int64 `json:"rx_bad_bytes"`
RxBroadcastPackets *int64 `json:"rx_broadcast_packets"`
RxBytesRate *int64 `json:"rx_bytes_rate"`
RxErrPackets *int64 `json:"rx_err_packets"`
RxFcsPackets *int64 `json:"rx_fcs_packets"`
RxFragmentsPackets *int64 `json:"rx_fragments_packets"`
RxGoodBytes *int64 `json:"rx_good_bytes"`
RxGoodPackets *int64 `json:"rx_good_packets"`
RxJabberPackets *int64 `json:"rx_jabber_packets"`
RxMulticastPackets *int64 `json:"rx_multicast_packets"`
RxOversizePackets *int64 `json:"rx_oversize_packets"`
RxPacketsRate *int64 `json:"rx_packets_rate"`
RxPause *int64 `json:"rx_pause"`
RxUndersizePackets *int64 `json:"rx_undersize_packets"`
RxUnicastPackets *int64 `json:"rx_unicast_packets"`
TxBroadcastPackets *int64 `json:"tx_broadcast_packets"`
TxBytes *int64 `json:"tx_bytes"`
TxBytesRate *int64 `json:"tx_bytes_rate"`
TxCollisions *int64 `json:"tx_collisions"`
TxDeferred *int64 `json:"tx_deferred"`
TxExcessive *int64 `json:"tx_excessive"`
TxFcs *int64 `json:"tx_fcs"`
TxLate *int64 `json:"tx_late"`
TxMulticastPackets *int64 `json:"tx_multicast_packets"`
TxMultiple *int64 `json:"tx_multiple"`
TxPackets *int64 `json:"tx_packets"`
TxPacketsRate *int64 `json:"tx_packets_rate"`
TxPause *int64 `json:"tx_pause"`
TxSingle *int64 `json:"tx_single"`
TxUnicastPackets *int64 `json:"tx_unicast_packets"`
}
// GetMetricsSystem http://mafreebox.freebox.fr/api/v5/system/
func (f *FreeboxConnection) GetMetricsSystem() (*MetricsFreeboxSystem, error) {
res := new(MetricsFreeboxSystem)
@ -136,3 +197,32 @@ func (f *FreeboxConnection) GetMetricsConnection() (*MetricsFreeboxConnectionAll
return result, nil
}
// GetMetricsSwitch http://mafreebox.freebox.fr/api/v5/switch/status/
func (f *FreeboxConnection) GetMetricsSwitch() (*MetricsFreeboxSwitch, error) {
res := new(MetricsFreeboxSwitch)
err := f.get("switch/status/", &res.Ports)
if err != nil {
return nil, err
}
wg := sync.WaitGroup{}
wg.Add(len(res.Ports))
for _, port := range res.Ports {
go func(port *MetricsFreeboxSwitchStatus) {
defer wg.Done()
stats := new(MetricsFreeboxSwitchPortStats)
// http://mafreebox.freebox.fr/api/v5/switch/port/1/stats
err := f.get(fmt.Sprintf("switch/port/%d/stats", port.ID), stats)
if err != nil {
log.Warning.Println("Could not get status of port", port.ID)
return
}
port.Stats = stats
}(port)
}
wg.Wait()
return res, err
}

View file

@ -27,6 +27,7 @@ func usage(err error) {
func main() {
debugPtr := flag.Bool("debug", false, "enable the debug mode")
listHostsPtr := flag.Bool("listHosts", false, "list the hosts connected to wifi and ethernet")
listenPtr := flag.String("listen", ":9091", "listen to address")
flag.Parse()
@ -41,7 +42,7 @@ func main() {
} else {
log.Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
}
collector := NewCollector(*debugPtr, args[0])
collector := NewCollector(args[0], *listHostsPtr, *debugPtr)
defer collector.Close()
prometheus.MustRegister(collector)