mirror of
https://github.com/nshttpd/mikrotik-exporter.git
synced 2024-11-25 11:46:36 +01:00
Merge pull request #120 from hafkensite/master
Add capsman station metric
This commit is contained in:
commit
4bfa7adfef
127
collector/capsman_collector.go
Normal file
127
collector/capsman_collector.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/routeros.v2/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type capsmanCollector struct {
|
||||||
|
props []string
|
||||||
|
descriptions map[string]*prometheus.Desc
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCapsmanCollector() routerOSCollector {
|
||||||
|
c := &capsmanCollector{}
|
||||||
|
c.init()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) init() {
|
||||||
|
//"rx-signal", "tx-signal",
|
||||||
|
c.props = []string{"interface", "mac-address", "ssid", "uptime", "tx-signal", "rx-signal", "packets", "bytes"}
|
||||||
|
labelNames := []string{"name", "address", "interface", "mac_address", "ssid"}
|
||||||
|
c.descriptions = make(map[string]*prometheus.Desc)
|
||||||
|
for _, p := range c.props[3 : len(c.props)-2] {
|
||||||
|
c.descriptions[p] = descriptionForPropertyName("capsman_station", p, labelNames)
|
||||||
|
}
|
||||||
|
for _, p := range c.props[len(c.props)-2:] {
|
||||||
|
c.descriptions["tx_"+p] = descriptionForPropertyName("capsman_station", "tx_"+p, labelNames)
|
||||||
|
c.descriptions["rx_"+p] = descriptionForPropertyName("capsman_station", "rx_"+p, labelNames)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) describe(ch chan<- *prometheus.Desc) {
|
||||||
|
for _, d := range c.descriptions {
|
||||||
|
ch <- d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) collect(ctx *collectorContext) error {
|
||||||
|
stats, err := c.fetch(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, re := range stats {
|
||||||
|
c.collectForStat(re, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) fetch(ctx *collectorContext) ([]*proto.Sentence, error) {
|
||||||
|
reply, err := ctx.client.Run("/caps-man/registration-table/print", "=.proplist="+strings.Join(c.props, ","))
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"device": ctx.device.Name,
|
||||||
|
"error": err,
|
||||||
|
}).Error("error fetching wlan station metrics")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply.Re, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) collectForStat(re *proto.Sentence, ctx *collectorContext) {
|
||||||
|
iface := re.Map["interface"]
|
||||||
|
mac := re.Map["mac-address"]
|
||||||
|
ssid := re.Map["ssid"]
|
||||||
|
|
||||||
|
for _, p := range c.props[3 : len(c.props)-2] {
|
||||||
|
c.collectMetricForProperty(p, iface, mac, ssid, re, ctx)
|
||||||
|
}
|
||||||
|
for _, p := range c.props[len(c.props)-2:] {
|
||||||
|
c.collectMetricForTXRXCounters(p, iface, mac, ssid, re, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) collectMetricForProperty(property, iface, mac, ssid string, re *proto.Sentence, ctx *collectorContext) {
|
||||||
|
if re.Map[property] == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p := re.Map[property]
|
||||||
|
i := strings.Index(p, "@")
|
||||||
|
if i > -1 {
|
||||||
|
p = p[:i]
|
||||||
|
}
|
||||||
|
var v float64
|
||||||
|
var err error
|
||||||
|
if property != "uptime" {
|
||||||
|
v, err = strconv.ParseFloat(p, 64)
|
||||||
|
} else {
|
||||||
|
v, err = parseDuration(p)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"device": ctx.device.Name,
|
||||||
|
"property": property,
|
||||||
|
"value": re.Map[property],
|
||||||
|
"error": err,
|
||||||
|
}).Error("error parsing capsman station metric value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
desc := c.descriptions[property]
|
||||||
|
ctx.ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, ctx.device.Name, ctx.device.Address, iface, mac, ssid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *capsmanCollector) collectMetricForTXRXCounters(property, iface, mac, ssid string, re *proto.Sentence, ctx *collectorContext) {
|
||||||
|
tx, rx, err := splitStringToFloats(re.Map[property])
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"device": ctx.device.Name,
|
||||||
|
"property": property,
|
||||||
|
"value": re.Map[property],
|
||||||
|
"error": err,
|
||||||
|
}).Error("error parsing capsman station metric value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
desc_tx := c.descriptions["tx_"+property]
|
||||||
|
desc_rx := c.descriptions["rx_"+property]
|
||||||
|
ctx.ch <- prometheus.MustNewConstMetric(desc_tx, prometheus.CounterValue, tx, ctx.device.Name, ctx.device.Address, iface, mac, ssid)
|
||||||
|
ctx.ch <- prometheus.MustNewConstMetric(desc_rx, prometheus.CounterValue, rx, ctx.device.Name, ctx.device.Address, iface, mac, ssid)
|
||||||
|
}
|
@ -139,6 +139,13 @@ func WithWlanSTA() Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithWlanIF enables wireless interface metrics
|
||||||
|
func WithCapsman() Option {
|
||||||
|
return func(c *collector) {
|
||||||
|
c.collectors = append(c.collectors, newCapsmanCollector())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithWlanIF enables wireless interface metrics
|
// WithWlanIF enables wireless interface metrics
|
||||||
func WithWlanIF() Option {
|
func WithWlanIF() Option {
|
||||||
return func(c *collector) {
|
return func(c *collector) {
|
||||||
|
@ -13,11 +13,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var durationRegex *regexp.Regexp
|
var durationRegex *regexp.Regexp
|
||||||
var durationParts [5]time.Duration
|
var durationParts [6]time.Duration
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
durationRegex = regexp.MustCompile(`(?:(\d*)w)?(?:(\d*)d)?(?:(\d*)h)?(?:(\d*)m)?(?:(\d*)s)?`)
|
durationRegex = regexp.MustCompile(`(?:(\d*)w)?(?:(\d*)d)?(?:(\d*)h)?(?:(\d*)m)?(?:(\d*)s)?(?:(\d*)ms)?`)
|
||||||
durationParts = [5]time.Duration{time.Hour * 168, time.Hour * 24, time.Hour, time.Minute, time.Second}
|
durationParts = [6]time.Duration{time.Hour * 168, time.Hour * 24, time.Hour, time.Minute, time.Second, time.Millisecond}
|
||||||
}
|
}
|
||||||
|
|
||||||
func metricStringCleanup(in string) string {
|
func metricStringCleanup(in string) string {
|
||||||
@ -39,7 +39,7 @@ func descriptionForPropertyNameHelpText(prefix, property string, labelNames []st
|
|||||||
|
|
||||||
func description(prefix, name, helpText string, labelNames []string) *prometheus.Desc {
|
func description(prefix, name, helpText string, labelNames []string) *prometheus.Desc {
|
||||||
return prometheus.NewDesc(
|
return prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, prefix, name),
|
prometheus.BuildFQName(namespace, prefix, metricStringCleanup(name)),
|
||||||
helpText,
|
helpText,
|
||||||
labelNames,
|
labelNames,
|
||||||
nil,
|
nil,
|
||||||
|
@ -24,6 +24,7 @@ type Config struct {
|
|||||||
Optics bool `yaml:"optics,omitempty"`
|
Optics bool `yaml:"optics,omitempty"`
|
||||||
W60G bool `yaml:"w60g,omitempty"`
|
W60G bool `yaml:"w60g,omitempty"`
|
||||||
WlanSTA bool `yaml:"wlansta,omitempty"`
|
WlanSTA bool `yaml:"wlansta,omitempty"`
|
||||||
|
Capsman bool `yaml:"capsman,omitempty"`
|
||||||
WlanIF bool `yaml:"wlanif,omitempty"`
|
WlanIF bool `yaml:"wlanif,omitempty"`
|
||||||
Monitor bool `yaml:"monitor,omitempty"`
|
Monitor bool `yaml:"monitor,omitempty"`
|
||||||
Ipsec bool `yaml:"ipsec,omitempty"`
|
Ipsec bool `yaml:"ipsec,omitempty"`
|
||||||
|
5
main.go
5
main.go
@ -50,6 +50,7 @@ var (
|
|||||||
withW60G = flag.Bool("with-w60g", false, "retrieves w60g interface metrics")
|
withW60G = flag.Bool("with-w60g", false, "retrieves w60g interface metrics")
|
||||||
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
|
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
|
||||||
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
|
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
|
||||||
|
withCapsman = flag.Bool("with-capsman", false, "retrieves capsman station metrics")
|
||||||
withMonitor = flag.Bool("with-monitor", false, "retrieves ethernet interface monitor info")
|
withMonitor = flag.Bool("with-monitor", false, "retrieves ethernet interface monitor info")
|
||||||
withIpsec = flag.Bool("with-ipsec", false, "retrieves ipsec metrics")
|
withIpsec = flag.Bool("with-ipsec", false, "retrieves ipsec metrics")
|
||||||
withLte = flag.Bool("with-lte", false, "retrieves lte metrics")
|
withLte = flag.Bool("with-lte", false, "retrieves lte metrics")
|
||||||
@ -238,6 +239,10 @@ func collectorOptions() []collector.Option {
|
|||||||
opts = append(opts, collector.WithWlanSTA())
|
opts = append(opts, collector.WithWlanSTA())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *withCapsman || cfg.Features.Capsman {
|
||||||
|
opts = append(opts, collector.WithCapsman())
|
||||||
|
}
|
||||||
|
|
||||||
if *withWlanIF || cfg.Features.WlanIF {
|
if *withWlanIF || cfg.Features.WlanIF {
|
||||||
opts = append(opts, collector.WithWlanIF())
|
opts = append(opts, collector.WithWlanIF())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user