Add health collector (#70)
* Add health collector for voltage & temperature * Run gofmt * Add help text to health collector
This commit is contained in:
@@ -90,6 +90,13 @@ func WithDHCPv6() Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithHealth enables board Health metrics
|
||||||
|
func WithHealth() Option {
|
||||||
|
return func(c *collector) {
|
||||||
|
c.collectors = append(c.collectors, newhealthCollector())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithPOE enables PoE metrics
|
// WithPOE enables PoE metrics
|
||||||
func WithPOE() Option {
|
func WithPOE() Option {
|
||||||
return func(c *collector) {
|
return func(c *collector) {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/routeros.v2/proto"
|
"gopkg.in/routeros.v2/proto"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dhcpLeaseCollector struct {
|
type dhcpLeaseCollector struct {
|
||||||
|
|||||||
93
collector/health_collector.go
Normal file
93
collector/health_collector.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"gopkg.in/routeros.v2/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type healthCollector struct {
|
||||||
|
props []string
|
||||||
|
descriptions map[string]*prometheus.Desc
|
||||||
|
}
|
||||||
|
|
||||||
|
func newhealthCollector() routerOSCollector {
|
||||||
|
c := &healthCollector{}
|
||||||
|
c.init()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthCollector) init() {
|
||||||
|
c.props = []string{"voltage", "temperature"}
|
||||||
|
|
||||||
|
labelNames := []string{"name", "address"}
|
||||||
|
helpText := []string{"Input voltage to the RouterOS board, in volts", "Temperature of RouterOS board, in degrees Celsius"}
|
||||||
|
c.descriptions = make(map[string]*prometheus.Desc)
|
||||||
|
for i, p := range c.props {
|
||||||
|
c.descriptions[p] = descriptionForPropertyNameHelpText("health", p, labelNames, helpText[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthCollector) describe(ch chan<- *prometheus.Desc) {
|
||||||
|
for _, d := range c.descriptions {
|
||||||
|
ch <- d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthCollector) 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 *healthCollector) fetch(ctx *collectorContext) ([]*proto.Sentence, error) {
|
||||||
|
reply, err := ctx.client.Run("/system/health/print", "=.proplist="+strings.Join(c.props, ","))
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"device": ctx.device.Name,
|
||||||
|
"error": err,
|
||||||
|
}).Error("error fetching system health metrics")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply.Re, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthCollector) collectForStat(re *proto.Sentence, ctx *collectorContext) {
|
||||||
|
for _, p := range c.props[:2] {
|
||||||
|
c.collectMetricForProperty(p, re, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *healthCollector) collectMetricForProperty(property string, re *proto.Sentence, ctx *collectorContext) {
|
||||||
|
var v float64
|
||||||
|
var err error
|
||||||
|
|
||||||
|
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 system health metric value")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
desc := c.descriptions[property]
|
||||||
|
ctx.ch <- prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, v, ctx.device.Name, ctx.device.Address)
|
||||||
|
}
|
||||||
@@ -13,9 +13,13 @@ func metricStringCleanup(in string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func descriptionForPropertyName(prefix, property string, labelNames []string) *prometheus.Desc {
|
func descriptionForPropertyName(prefix, property string, labelNames []string) *prometheus.Desc {
|
||||||
|
return descriptionForPropertyNameHelpText(prefix, property, labelNames, property)
|
||||||
|
}
|
||||||
|
|
||||||
|
func descriptionForPropertyNameHelpText(prefix, property string, labelNames []string, helpText string) *prometheus.Desc {
|
||||||
return prometheus.NewDesc(
|
return prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(namespace, prefix, metricStringCleanup(property)),
|
prometheus.BuildFQName(namespace, prefix, metricStringCleanup(property)),
|
||||||
property,
|
helpText,
|
||||||
labelNames,
|
labelNames,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type Config struct {
|
|||||||
DHCP bool `yaml:"dhcp,omitempty"`
|
DHCP bool `yaml:"dhcp,omitempty"`
|
||||||
DHCPL bool `yaml:"dhcpl,omitempty"`
|
DHCPL bool `yaml:"dhcpl,omitempty"`
|
||||||
DHCPv6 bool `yaml:"dhcpv6,omitempty"`
|
DHCPv6 bool `yaml:"dhcpv6,omitempty"`
|
||||||
|
Health bool `yaml:"health,omitempty"`
|
||||||
Routes bool `yaml:"routes,omitempty"`
|
Routes bool `yaml:"routes,omitempty"`
|
||||||
POE bool `yaml:"poe,omitempty"`
|
POE bool `yaml:"poe,omitempty"`
|
||||||
Pools bool `yaml:"pools,omitempty"`
|
Pools bool `yaml:"pools,omitempty"`
|
||||||
|
|||||||
5
main.go
5
main.go
@@ -41,6 +41,7 @@ var (
|
|||||||
withDHCP = flag.Bool("with-dhcp", false, "retrieves DHCP server metrics")
|
withDHCP = flag.Bool("with-dhcp", false, "retrieves DHCP server metrics")
|
||||||
withDHCPL = flag.Bool("with-dhcpl", false, "retrieves DHCP server lease metrics")
|
withDHCPL = flag.Bool("with-dhcpl", false, "retrieves DHCP server lease metrics")
|
||||||
withDHCPv6 = flag.Bool("with-dhcpv6", false, "retrieves DHCPv6 server metrics")
|
withDHCPv6 = flag.Bool("with-dhcpv6", false, "retrieves DHCPv6 server metrics")
|
||||||
|
withHealth = flag.Bool("with-health", false, "retrieves board Health metrics")
|
||||||
withPOE = flag.Bool("with-poe", false, "retrieves PoE metrics")
|
withPOE = flag.Bool("with-poe", false, "retrieves PoE metrics")
|
||||||
withPools = flag.Bool("with-pools", false, "retrieves IP(v6) pool metrics")
|
withPools = flag.Bool("with-pools", false, "retrieves IP(v6) pool metrics")
|
||||||
withOptics = flag.Bool("with-optics", false, "retrieves optical diagnostic metrics")
|
withOptics = flag.Bool("with-optics", false, "retrieves optical diagnostic metrics")
|
||||||
@@ -198,6 +199,10 @@ func collectorOptions() []collector.Option {
|
|||||||
opts = append(opts, collector.WithDHCPv6())
|
opts = append(opts, collector.WithDHCPv6())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *withHealth || cfg.Features.Health {
|
||||||
|
opts = append(opts, collector.WithHealth())
|
||||||
|
}
|
||||||
|
|
||||||
if *withPOE || cfg.Features.POE {
|
if *withPOE || cfg.Features.POE {
|
||||||
opts = append(opts, collector.WithPOE())
|
opts = append(opts, collector.WithPOE())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user