Skip to content

Commit

Permalink
Merge pull request #7 from wbollock/feat/https_support
Browse files Browse the repository at this point in the history
feat!: https and timeout support
  • Loading branch information
wbollock authored Sep 5, 2022
2 parents 2f0dc92 + f1d6c91 commit eafa0ba
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 22 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ Create a simple `config.toml` in `/etc/prometheus-nagios-exporter` with your Nag
APIKey = ""
```

By default this will point to localhost, but a remote address can be specified with `--web.remote-address`. The default port is `9111`, but can be changed with `--web.listen-address`.
By default this will point to `http://localhost`, but a remote address can be specified with `--nagios.scrape-uri`. The default port is `9111`, but can be changed with `--web.listen-address`.

SSL support is included for scraping remote Nagios endpoints, and SSL verification can be enabled/disabled with `--nagios.ssl-verify`. A scrape timeout value is also available with `--nagios.timeout`.

```bash
./nagios_exporter --nagios.scrape-uri https://<my-tls-url> --nagios.ssl-verify true --nagios.timeout 5
```

To see all available configuration flags:

Expand Down
60 changes: 40 additions & 20 deletions nagios_exporter.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package main

import (
"crypto/tls"
"encoding/json"
"flag"
"io"
"net/http"
"time"

"github.com/BurntSushi/toml"
"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -153,12 +155,16 @@ var (

type Exporter struct {
nagiosEndpoint, nagiosAPIKey string
sslVerify bool
nagiosAPITimeout time.Duration
}

func NewExporter(nagiosEndpoint, nagiosAPIKey string) *Exporter {
func NewExporter(nagiosEndpoint, nagiosAPIKey string, sslVerify bool, nagiosAPITimeout time.Duration) *Exporter {
return &Exporter{
nagiosEndpoint: nagiosEndpoint,
nagiosAPIKey: nagiosAPIKey,
nagiosEndpoint: nagiosEndpoint,
nagiosAPIKey: nagiosAPIKey,
sslVerify: sslVerify,
nagiosAPITimeout: nagiosAPITimeout,
}
}

Expand Down Expand Up @@ -186,11 +192,11 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
ch <- servicechecksPerformance
}

func (e *Exporter) TestNagiosConnectivity() float64 {
func (e *Exporter) TestNagiosConnectivity(sslVerify bool, nagiosAPITimeout time.Duration) float64 {

systemStatusURL := e.nagiosEndpoint + systemstatusAPI + "?apikey=" + e.nagiosAPIKey

body := QueryAPIs(systemStatusURL)
body := QueryAPIs(systemStatusURL, sslVerify, nagiosAPITimeout)
log.Debug("Queried API: ", systemstatusAPI)

systemStatusObject := systemStatus{}
Expand All @@ -205,7 +211,7 @@ func (e *Exporter) TestNagiosConnectivity() float64 {

func (e *Exporter) Collect(ch chan<- prometheus.Metric) {

nagiosStatus := e.TestNagiosConnectivity()
nagiosStatus := e.TestNagiosConnectivity(e.sslVerify, e.nagiosAPITimeout)

if nagiosStatus == 0 {
log.Warn("Cannot connect to Nagios endpoint")
Expand All @@ -215,11 +221,20 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
up, prometheus.GaugeValue, nagiosStatus,
)

e.QueryAPIsAndUpdateMetrics(ch)
e.QueryAPIsAndUpdateMetrics(ch, e.sslVerify, e.nagiosAPITimeout)

}

func QueryAPIs(url string) (body []byte) {
func QueryAPIs(url string, sslVerify bool, nagiosAPITimeout time.Duration) (body []byte) {

// https://github.com/prometheus/haproxy_exporter/blob/main/haproxy_exporter.go#L337-L345

tr := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: !sslVerify}}

client := http.Client{
Timeout: nagiosAPITimeout,
Transport: tr,
}

req, err := http.NewRequest("GET", url, nil)

Expand All @@ -230,16 +245,16 @@ func QueryAPIs(url string) (body []byte) {
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Prometheus")

resp, err := http.DefaultClient.Do(req)
resp, err := client.Do(req)

if err != nil {
log.Warn(err)
log.Fatal(err)
}

if resp.Body != nil {
defer resp.Body.Close()
} else {
log.Warn("HTTP response body is nil - check API connectivity")
log.Fatal("HTTP response body is nil - check API connectivity")
}

body, readErr := io.ReadAll(resp.Body)
Expand All @@ -251,13 +266,13 @@ func QueryAPIs(url string) (body []byte) {
return body
}

func (e *Exporter) QueryAPIsAndUpdateMetrics(ch chan<- prometheus.Metric) {
func (e *Exporter) QueryAPIsAndUpdateMetrics(ch chan<- prometheus.Metric, sslVerify bool, nagiosAPITimeout time.Duration) {

// get system status
systeminfoURL := e.nagiosEndpoint + systeminfoAPI + "?apikey=" + e.nagiosAPIKey
log.Debug("Queried API: ", systeminfoAPI)

body := QueryAPIs(systeminfoURL)
body := QueryAPIs(systeminfoURL, sslVerify, nagiosAPITimeout)

systemInfoObject := systemInfo{}
jsonErr := json.Unmarshal(body, &systemInfoObject)
Expand All @@ -272,7 +287,7 @@ func (e *Exporter) QueryAPIsAndUpdateMetrics(ch chan<- prometheus.Metric) {
// host status
hoststatusURL := e.nagiosEndpoint + hoststatusAPI + "?apikey=" + e.nagiosAPIKey

body = QueryAPIs(hoststatusURL)
body = QueryAPIs(hoststatusURL, sslVerify, nagiosAPITimeout)
log.Debug("Queried API: ", systeminfoAPI)

hostStatusObject := hostStatus{}
Expand Down Expand Up @@ -357,7 +372,7 @@ func (e *Exporter) QueryAPIsAndUpdateMetrics(ch chan<- prometheus.Metric) {
// service status
servicestatusURL := e.nagiosEndpoint + servicestatusAPI + "?apikey=" + e.nagiosAPIKey

body = QueryAPIs(servicestatusURL)
body = QueryAPIs(servicestatusURL, sslVerify, nagiosAPITimeout)
log.Debug("Queried API: ", servicestatusAPI)

serviceStatusObject := serviceStatus{}
Expand Down Expand Up @@ -459,7 +474,7 @@ func (e *Exporter) QueryAPIsAndUpdateMetrics(ch chan<- prometheus.Metric) {
// service status
systemStatusDetailURL := e.nagiosEndpoint + systemstatusDetailAPI + "?apikey=" + e.nagiosAPIKey

body = QueryAPIs(systemStatusDetailURL)
body = QueryAPIs(systemStatusDetailURL, sslVerify, nagiosAPITimeout)
log.Debug("Queried API: ", systemstatusDetailAPI)

systemStatusDetailObject := systemStatusDetail{}
Expand Down Expand Up @@ -573,8 +588,13 @@ func main() {
"Address to listen on for telemetry")
metricsPath = flag.String("web.telemetry-path", "/metrics",
"Path under which to expose metrics")
remoteAddress = flag.String("web.remote-address", "localhost",
remoteAddress = flag.String("nagios.scrape-uri", "http://localhost",
"Nagios application address")
sslVerify = flag.Bool("nagios.ssl-verify", false,
"SSL certificate validation")
// I think users would rather enter `5` over `5s`, e.g int vs Duration flag
nagiosAPITimeout = flag.Int("nagios.timeout", 5,
"Timeout for querying Nagios API in seconds")
configPath = flag.String("config.path", "/etc/prometheus-nagios-exporter/config.toml",
"Config file path")
logLevel = flag.String("log.level", "info",
Expand All @@ -592,10 +612,10 @@ func main() {

var conf Config = ReadConfig(*configPath)

// TODO - HTTPS support
nagiosURL := "http://" + *remoteAddress + nagiosAPIVersion + apiSlug
nagiosURL := *remoteAddress + nagiosAPIVersion + apiSlug

exporter := NewExporter(nagiosURL, conf.APIKey)
// convert timeout flag to seconds
exporter := NewExporter(nagiosURL, conf.APIKey, *sslVerify, time.Duration(*nagiosAPITimeout)*time.Second)
prometheus.MustRegister(exporter)

log.Info("Using connection endpoint: ", *remoteAddress)
Expand Down
2 changes: 1 addition & 1 deletion nfpm/etc/default/prometheus-nagios-exporter
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Prometheus Nagios Exporter default arguments
ARGS="-config.path /etc/prometheus-nagios-exporter/config.toml -web.remote-address localhost"
ARGS="--config.path /etc/prometheus-nagios-exporter/config.toml --nagios.scrape-uri http://localhost"

0 comments on commit eafa0ba

Please sign in to comment.