mirror of
https://github.com/nshttpd/mikrotik-exporter.git
synced 2024-11-16 10:25:12 +01:00
55ae663ce3
Adds ability to specify API Port, either via CLI or in config. If port is not provided, default is used, taking into account if TLS is enabled or not
234 lines
6.0 KiB
Go
234 lines
6.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"io/ioutil"
|
|
"os"
|
|
|
|
"github.com/prometheus/common/version"
|
|
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"mikrotik-exporter/collector"
|
|
"mikrotik-exporter/config"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// single device can be defined via CLI flags, multiple via config file.
|
|
var (
|
|
address = flag.String("address", "", "address of the device to monitor")
|
|
configFile = flag.String("config-file", "", "config file to load")
|
|
device = flag.String("device", "", "single device to monitor")
|
|
insecure = flag.Bool("insecure", false, "skips verification of server certificate when using TLS (not recommended)")
|
|
logFormat = flag.String("log-format", "json", "logformat text or json (default json)")
|
|
logLevel = flag.String("log-level", "info", "log level")
|
|
metricsPath = flag.String("path", "/metrics", "path to answer requests on")
|
|
password = flag.String("password", "", "password for authentication for single device")
|
|
deviceport = flag.String("deviceport", "8728", "port for single device")
|
|
port = flag.String("port", ":9436", "port number to listen on")
|
|
timeout = flag.Duration("timeout", collector.DefaultTimeout, "timeout when connecting to devices")
|
|
tls = flag.Bool("tls", false, "use tls to connect to routers")
|
|
user = flag.String("user", "", "user for authentication with single device")
|
|
ver = flag.Bool("version", false, "find the version of binary")
|
|
|
|
withBgp = flag.Bool("with-bgp", false, "retrieves BGP routing infrormation")
|
|
withRoutes = flag.Bool("with-routes", false, "retrieves routing table information")
|
|
withDHCP = flag.Bool("with-dhcp", false, "retrieves DHCP server metrics")
|
|
withDHCPv6 = flag.Bool("with-dhcpv6", false, "retrieves DHCPv6 server metrics")
|
|
withPOE = flag.Bool("with-poe", false, "retrieves PoE metrics")
|
|
withPools = flag.Bool("with-pools", false, "retrieves IP(v6) pool metrics")
|
|
withOptics = flag.Bool("with-optics", false, "retrieves optical diagnostic metrics")
|
|
withWlanSTA = flag.Bool("with-wlansta", false, "retrieves connected wlan station metrics")
|
|
withWlanIF = flag.Bool("with-wlanif", false, "retrieves wlan interface metrics")
|
|
withMonitor = flag.Bool("with-monitor", false, "retrieves ethernet interface monitor info")
|
|
withIpsec = flag.Bool("with-ipsec", false, "retrieves ipsec metrics")
|
|
|
|
cfg *config.Config
|
|
|
|
appVersion = "DEVELOPMENT"
|
|
shortSha = "0xDEADBEEF"
|
|
)
|
|
|
|
func init() {
|
|
prometheus.MustRegister(version.NewCollector("mikrotik_exporter"))
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
if *ver {
|
|
fmt.Printf("\nVersion: %s\nShort SHA: %s\n\n", appVersion, shortSha)
|
|
os.Exit(0)
|
|
}
|
|
|
|
configureLog()
|
|
|
|
c, err := loadConfig()
|
|
if err != nil {
|
|
log.Errorf("Could not load config: %v", err)
|
|
os.Exit(3)
|
|
}
|
|
cfg = c
|
|
|
|
startServer()
|
|
}
|
|
|
|
func configureLog() {
|
|
ll, err := log.ParseLevel(*logLevel)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
log.SetLevel(ll)
|
|
|
|
if *logFormat == "text" {
|
|
log.SetFormatter(&log.TextFormatter{})
|
|
} else {
|
|
log.SetFormatter(&log.JSONFormatter{})
|
|
}
|
|
}
|
|
|
|
func loadConfig() (*config.Config, error) {
|
|
if *configFile != "" {
|
|
return loadConfigFromFile()
|
|
}
|
|
|
|
return loadConfigFromFlags()
|
|
}
|
|
|
|
func loadConfigFromFile() (*config.Config, error) {
|
|
b, err := ioutil.ReadFile(*configFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return config.Load(bytes.NewReader(b))
|
|
}
|
|
|
|
func loadConfigFromFlags() (*config.Config, error) {
|
|
if *device == "" || *address == "" || *user == "" || *password == "" {
|
|
return nil, fmt.Errorf("missing required param for single device configuration")
|
|
}
|
|
|
|
return &config.Config{
|
|
Devices: []config.Device{
|
|
config.Device{
|
|
Name: *device,
|
|
Address: *address,
|
|
User: *user,
|
|
Password: *password,
|
|
Port: *deviceport,
|
|
},
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func startServer() {
|
|
h, err := createMetricsHandler()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
http.Handle(*metricsPath, h)
|
|
|
|
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
|
_, _ = w.Write([]byte("ok"))
|
|
})
|
|
|
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
_, _ = w.Write([]byte(`<html>
|
|
<head><title>Mikrotik Exporter</title></head>
|
|
<body>
|
|
<h1>Mikrotik Exporter</h1>
|
|
<p><a href="` + *metricsPath + `">Metrics</a></p>
|
|
</body>
|
|
</html>`))
|
|
})
|
|
|
|
log.Info("Listening on ", *port)
|
|
log.Fatal(http.ListenAndServe(*port, nil))
|
|
}
|
|
|
|
func createMetricsHandler() (http.Handler, error) {
|
|
opts := collectorOptions()
|
|
nc, err := collector.NewCollector(cfg, opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
registry := prometheus.NewRegistry()
|
|
err = registry.Register(nc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return promhttp.HandlerFor(registry,
|
|
promhttp.HandlerOpts{
|
|
ErrorLog: log.New(),
|
|
ErrorHandling: promhttp.ContinueOnError,
|
|
}), nil
|
|
}
|
|
|
|
func collectorOptions() []collector.Option {
|
|
opts := []collector.Option{}
|
|
|
|
if *withBgp || cfg.Features.BGP {
|
|
opts = append(opts, collector.WithBGP())
|
|
}
|
|
|
|
if *withRoutes || cfg.Features.Routes {
|
|
opts = append(opts, collector.WithRoutes())
|
|
}
|
|
|
|
if *withDHCP || cfg.Features.DHCP {
|
|
opts = append(opts, collector.WithDHCP())
|
|
}
|
|
|
|
if *withDHCPv6 || cfg.Features.DHCPv6 {
|
|
opts = append(opts, collector.WithDHCPv6())
|
|
}
|
|
|
|
if *withPOE || cfg.Features.POE {
|
|
opts = append(opts, collector.WithPOE())
|
|
}
|
|
|
|
if *withPools || cfg.Features.Pools {
|
|
opts = append(opts, collector.WithPools())
|
|
}
|
|
|
|
if *withOptics || cfg.Features.Optics {
|
|
opts = append(opts, collector.WithOptics())
|
|
}
|
|
|
|
if *withWlanSTA || cfg.Features.WlanSTA {
|
|
opts = append(opts, collector.WithWlanSTA())
|
|
}
|
|
|
|
if *withWlanIF || cfg.Features.WlanIF {
|
|
opts = append(opts, collector.WithWlanIF())
|
|
}
|
|
|
|
if *withMonitor || cfg.Features.Monitor {
|
|
opts = append(opts, collector.Monitor())
|
|
|
|
}
|
|
|
|
if *withIpsec || cfg.Features.Ipsec {
|
|
opts = append(opts, collector.WithIpsec())
|
|
}
|
|
|
|
if *timeout != collector.DefaultTimeout {
|
|
opts = append(opts, collector.WithTimeout(*timeout))
|
|
}
|
|
|
|
if *tls {
|
|
opts = append(opts, collector.WithTLS(*insecure))
|
|
}
|
|
|
|
return opts
|
|
}
|