Skip to content

Commit beb09ce

Browse files
authored
[ci skip] monitor data for ethernet ports (#45)
* fix import name conflict * adding in ethernet monitor information via prometheus gauge * set CGO_ENABLED env var on build
1 parent ea9cc69 commit beb09ce

File tree

6 files changed

+141
-4
lines changed

6 files changed

+141
-4
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ utils:
1414
go get github.com/tcnksm/ghr
1515

1616
deploy: utils
17-
gox -os="linux freebsd netbsd" -arch="amd64 arm arm64 386" -parallel=4 -ldflags "$(LDFLAGS)" -output "dist/mikrotik-exporter_{{.OS}}_{{.Arch}}"
17+
CGO_ENABLED=0 gox -os="linux freebsd netbsd" -arch="amd64 arm arm64 386" -parallel=4 -ldflags "$(LDFLAGS)" -output "dist/mikrotik-exporter_{{.OS}}_{{.Arch}}"
1818
ghr -t $(GITHUB_TOKEN) -u $(CIRCLE_PROJECT_USERNAME) -r $(CIRCLE_PROJECT_REPONAME) -replace $(VERSION) dist/
1919

2020
dockerhub: deploy

collector/collector.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ func WithWlanIF() Option {
105105
}
106106
}
107107

108+
// WithMonitor enables ethernet monitor collector metrics
109+
func Monitor() Option {
110+
return func(c *collector) {
111+
c.collectors = append(c.collectors, newMonitorCollector())
112+
}
113+
}
114+
108115
// WithTimeout sets timeout for connecting to router
109116
func WithTimeout(d time.Duration) Option {
110117
return func(c *collector) {

collector/helper.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ func description(prefix, name, helpText string, labelNames []string) *prometheus
3131
}
3232

3333
func splitStringToFloats(metric string) (float64, float64, error) {
34-
strings := strings.Split(metric, ",")
34+
strs := strings.Split(metric, ",")
3535

36-
m1, err := strconv.ParseFloat(strings[0], 64)
36+
m1, err := strconv.ParseFloat(strs[0], 64)
3737
if err != nil {
3838
return math.NaN(), math.NaN(), err
3939
}
40-
m2, err := strconv.ParseFloat(strings[1], 64)
40+
m2, err := strconv.ParseFloat(strs[1], 64)
4141
if err != nil {
4242
return math.NaN(), math.NaN(), err
4343
}

collector/monitor_collector.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package collector
2+
3+
import (
4+
"strings"
5+
6+
"gopkg.in/routeros.v2/proto"
7+
8+
"github.com/prometheus/client_golang/prometheus"
9+
log "github.com/sirupsen/logrus"
10+
)
11+
12+
type monitorCollector struct {
13+
props []string // props from monitor, can add other ether props later if needed
14+
descriptions map[string]*prometheus.Desc
15+
}
16+
17+
func newMonitorCollector() routerOSCollector {
18+
c := &monitorCollector{}
19+
c.init()
20+
return c
21+
}
22+
23+
func (c *monitorCollector) init() {
24+
c.props = []string{"status", "rate", "full-duplex"}
25+
labelNames := []string{"name", "address", "interface"}
26+
c.descriptions = make(map[string]*prometheus.Desc)
27+
for _, p := range c.props {
28+
c.descriptions[p] = descriptionForPropertyName("monitor", p, labelNames)
29+
}
30+
}
31+
32+
func (c *monitorCollector) describe(ch chan<- *prometheus.Desc) {
33+
for _, d := range c.descriptions {
34+
ch <- d
35+
}
36+
}
37+
38+
func (c *monitorCollector) collect(ctx *collectorContext) error {
39+
reply, err := ctx.client.Run("/interface/ethernet/print", "=.proplist=name")
40+
if err != nil {
41+
log.WithFields(log.Fields{
42+
"device": ctx.device.Name,
43+
"error": err,
44+
}).Error("error fetching ethernet interfaces")
45+
return err
46+
}
47+
48+
eths := make([]string, len(reply.Re))
49+
for idx, eth := range reply.Re {
50+
eths[idx] = eth.Map["name"]
51+
}
52+
53+
return c.collectForMonitor(eths, ctx)
54+
}
55+
56+
func (c *monitorCollector) collectForMonitor(eths []string, ctx *collectorContext) error {
57+
reply, err := ctx.client.Run("/interface/ethernet/monitor",
58+
"=numbers="+strings.Join(eths, ","),
59+
"=once=",
60+
"=.proplist=name,"+strings.Join(c.props, ","))
61+
62+
if err != nil {
63+
log.WithFields(log.Fields{
64+
"device": ctx.device.Name,
65+
"error": err,
66+
}).Error("error fetching ethernet monitor info")
67+
return err
68+
}
69+
70+
for _, e := range reply.Re {
71+
c.collectMetricsForEth(e.Map["name"], e, ctx)
72+
}
73+
74+
return nil
75+
}
76+
77+
func (c *monitorCollector) collectMetricsForEth(name string, se *proto.Sentence, ctx *collectorContext) {
78+
for _, prop := range c.props {
79+
v, ok := se.Map[prop]
80+
if !ok {
81+
continue
82+
}
83+
84+
value := float64(c.valueForProp(prop, v))
85+
86+
ctx.ch <- prometheus.MustNewConstMetric(c.descriptions[prop], prometheus.GaugeValue, value, ctx.device.Name, ctx.device.Address, name)
87+
88+
}
89+
90+
}
91+
92+
func (c *monitorCollector) valueForProp(name, value string) int {
93+
switch {
94+
case name == "status":
95+
return func(v string) int {
96+
if v == "link-ok" {
97+
return 1
98+
}
99+
return 0
100+
}(value)
101+
case name == "rate":
102+
return func(v string) int {
103+
switch {
104+
case v == "10Mbps":
105+
return 10
106+
case v == "100Mbps":
107+
return 100
108+
case v == "1Gbps":
109+
return 1000
110+
}
111+
return 0
112+
}(value)
113+
case name == "full-duplex":
114+
return func(v string) int {
115+
if v == "true" {
116+
return 1
117+
}
118+
return 0
119+
}(value)
120+
default:
121+
return 0
122+
}
123+
}

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type Config struct {
1919
Optics bool `yaml:"optics,omitempty"`
2020
WlanSTA bool `yaml:"wlansta,omitempty"`
2121
WlanIF bool `yaml:"wlanif,omitempty"`
22+
Monitor bool `yaml:"monitor,omitempty"`
2223
} `yaml:"features,omitempty"`
2324
}
2425

main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var (
3636
withOptics = flag.Bool("with-optics", false, "retrieves optical diagnostic metrics")
3737
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
3838
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
39+
withMonitor = flag.Bool("with-monitor", false, "retrieves ethernet interface monitor info")
3940
timeout = flag.Duration("timeout", collector.DefaultTimeout, "timeout when connecting to devices")
4041
tls = flag.Bool("tls", false, "use tls to connect to routers")
4142
insecure = flag.Bool("insecure", false, "skips verification of server certificate when using TLS (not recommended)")
@@ -190,6 +191,11 @@ func collectorOptions() []collector.Option {
190191
opts = append(opts, collector.WithWlanIF())
191192
}
192193

194+
if *withMonitor || cfg.Features.Monitor {
195+
opts = append(opts, collector.Monitor())
196+
197+
}
198+
193199
if *timeout != collector.DefaultTimeout {
194200
opts = append(opts, collector.WithTimeout(*timeout))
195201
}

0 commit comments

Comments
 (0)