Skip to content
Snippets Groups Projects
Commit 093c7a59 authored by Jan Grewe's avatar Jan Grewe
Browse files

Initial commit

parents
Branches
No related tags found
No related merge requests found
gitlab-token-injector
vendor
nexenta_exporter
hash: 0bbc534a255abb51b978492c5d43b4ae0f7a8c89e969571a8b7979d1ddaea9a8
updated: 2018-06-05T16:46:38.641011889+02:00
imports:
- name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
subpackages:
- quantile
- name: github.com/golang/protobuf
version: 7a211bcf3bce0e3f1d74f9894916e6f116ae83b4
subpackages:
- proto
- name: github.com/matttproud/golang_protobuf_extensions
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
subpackages:
- pbutil
- name: github.com/prometheus/client_golang
version: 967789050ba94deca04a5e84cce8ad472ce313c1
subpackages:
- prometheus
- prometheus/promhttp
- name: github.com/prometheus/client_model
version: 6f3806018612930941127f2a7c6c453ba2c527d2
subpackages:
- go
- name: github.com/prometheus/common
version: 13ba4ddd0caa9c28ca7b7bffe1dfa9ed8d5ef207
subpackages:
- expfmt
- internal/bitbucket.org/ww/goautoneg
- log
- model
- version
- name: github.com/prometheus/procfs
version: 65c1f6f8f0fc1e2185eb9863a3bc751496404259
subpackages:
- xfs
- name: github.com/Sirupsen/logrus
version: ea8897e79973357ba785ac2533559a6297e83c44
- name: golang.org/x/crypto
version: df8d4716b3472e4a531c33cedbe537dae921a1a9
subpackages:
- ssh/terminal
- name: golang.org/x/sys
version: c11f84a56e43e20a78cee75a7c034031ecf57d1f
subpackages:
- unix
- windows
- windows/registry
- windows/svc/eventlog
testImports: []
package: gitlab.mfb.io/devops/nexenta-exporter
import:
- package: github.com/prometheus/client_golang
version: ~0.9.0-pre1
subpackages:
- prometheus/promhttp
- prometheus
- package: github.com/prometheus/common
subpackages:
- log
- version
main.go 0 → 100644
package main
import (
"flag"
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
"fmt"
"os"
"github.com/prometheus/common/log"
"github.com/prometheus/common/version"
"github.com/prometheus/client_golang/prometheus"
"sync"
"crypto/tls"
"io/ioutil"
"encoding/json"
"bytes"
)
const (
namespace = "nexenta" // For Prometheus metrics.
apiPath = "/rest/nms"
)
var (
listenAddr = flag.String("listen-address", ":9457", "The address to listen on for HTTP requests.")
metricsEndpoint = flag.String("metrics-endpoint", "/metrics", "Path under which to expose metrics.")
apiHost = flag.String("host", "nexenta", "Nexenta API host.")
apiPort = flag.String("port", "8457", "Nexenta API port.")
apiUser = flag.String("user", "admin", "Nexenta API username.")
apiPass = flag.String("password", "password", "Nexenta API password.")
apiSsl = flag.Bool("ssl", false, "Use SSL for the Nexenta API.")
insecure = flag.Bool("insecure", false, "Ignore server certificate if using https.")
showVersion = flag.Bool("version", false, "Print version information.")
)
type ApiResponse struct {
TGFlash string `json:"tg_flash"`
Result interface{} `json:"result"`
Error interface{} `json:"error"`
}
type ResultObject struct {
State []string `json:"state"`
Errors []string `json:"errors"`
}
type Exporter struct {
URI string
mutex sync.Mutex
client *http.Client
up *prometheus.Desc
scrapeFailures prometheus.Counter
volumeOnline *prometheus.Desc
}
func NewExporter(uri string) *Exporter {
return &Exporter{
URI: uri,
up: prometheus.NewDesc(
prometheus.BuildFQName(namespace, "", "up"),
"Could the Nexenta API be reached",
nil,
nil),
scrapeFailures: prometheus.NewCounter(prometheus.CounterOpts{
Namespace: namespace,
Name: "exporter_scrape_failures_total",
Help: "Number of errors while scraping Nexenta API.",
}),
volumeOnline: prometheus.NewDesc(
prometheus.BuildFQName(namespace, "volume", "online"),
"Status of volume.",
[]string{"volume"},
nil,
),
client: &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: *insecure},
},
},
}
}
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
ch <- e.up
e.scrapeFailures.Describe(ch)
ch <- e.volumeOnline
}
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
e.mutex.Lock() // To protect metrics from concurrent collects.
defer e.mutex.Unlock()
err := e.collect(ch)
if err != nil {
log.Errorf("Collect(): %v", err)
}
return
}
func (e *Exporter) collect(ch chan<- prometheus.Metric) error {
volumes, err := e.getVolumes(ch)
if err != nil {
log.Errorf("getVolumes(): %v", err)
}
if len(volumes) > 0 {
for _, volume := range volumes {
err := e.getVolumeStatus(ch, volume)
if err != nil {
log.Errorf("getVolumeStatus(): %v", err)
}
}
}
if err != nil {
ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0)
return fmt.Errorf("Error scraping Nexenta API: %v", err)
}
ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1)
return err
}
func (e *Exporter) getVolumes(ch chan<- prometheus.Metric) ([]string, error) {
var reqJson = []byte(`{"object": "volume", "params": [""], "method": "get_names"}`)
apiResponse, err := e.queryApi(ch, reqJson); if err != nil { return nil, err }
apiResult, err := json.Marshal(apiResponse.Result)
var volumes []string
err = json.Unmarshal([]byte(apiResult), &volumes)
return volumes, err
}
func (e *Exporter) getVolumeStatus(ch chan<- prometheus.Metric, volume string) error {
var reqJson = []byte(`{"object": "volume", "params": ["` + volume + `"], "method": "get_status"}`)
apiResponse, err := e.queryApi(ch, reqJson); if err != nil { return err }
apiResult, err := json.Marshal(apiResponse.Result)
var result= new(ResultObject)
err = json.Unmarshal(apiResult, &result)
var volumeOnline float64 = 0
if len(result.State) > 0 {
if result.State[0] == "ONLINE" { volumeOnline = 1 }
}
ch <- prometheus.MustNewConstMetric(e.volumeOnline, prometheus.GaugeValue, volumeOnline, "data")
return err
}
func (e *Exporter) queryApi(ch chan<- prometheus.Metric, reqJson []byte) (*ApiResponse, error) {
resp, err := e.client.Post(e.URI, "application/json", bytes.NewBuffer(reqJson))
data, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if resp.StatusCode != 200 {
if err != nil {
data = []byte(err.Error())
log.Errorf("Error scraping Nexenta API: %s", err)
e.scrapeFailures.Inc()
e.scrapeFailures.Collect(ch)
}
return nil, fmt.Errorf("Status %s (%d)", resp.Status, resp.StatusCode)
}
//log.Infof("response: %s", data)
var apiResponse = new(ApiResponse)
err_json := json.Unmarshal(data, &apiResponse)
if err_json != nil {
log.Infof("whoops:", err_json)
}
if apiResponse.Result == nil {
e.scrapeFailures.Inc()
e.scrapeFailures.Collect(ch)
return nil, fmt.Errorf("Field 'result' in API response is null")
}
return apiResponse, nil
}
func main() {
flag.Parse()
if *showVersion {
fmt.Fprintln(os.Stdout, version.Print("nexenta_exporter"))
os.Exit(0)
}
exporter := NewExporter("http://" + *apiUser + ":" + *apiPass + "@" + *apiHost + ":" + *apiPort + apiPath)
prometheus.MustRegister(exporter)
prometheus.MustRegister(version.NewCollector("nexenta_exporter"))
// disable Go metrics
prometheus.Unregister(prometheus.NewProcessCollector(os.Getpid(), ""))
prometheus.Unregister(prometheus.NewGoCollector())
log.Infoln("Starting nexenta_exporter", version.Info())
log.Infoln("Build context", version.BuildContext())
log.Infof("Starting Server: %s", *listenAddr)
http.Handle(*metricsEndpoint, promhttp.Handler())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`<html>
<head><title>Nexenta Exporter</title></head>
<body>
<h1>Nexenta Exporter</h1>
<p><a href='` + *metricsEndpoint + `'>Metrics</a></p>
</body>
</html>`))
})
log.Fatal(http.ListenAndServe(*listenAddr, nil))
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment