diff --git a/main.go b/main.go index 25a3a3a6242421200a708925b8c357a9373d51e0..0d66446250537ae2e98a10fb0a47cec520df1586 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,8 @@ import ( "io/ioutil" "encoding/json" "bytes" + "strconv" + "strings" ) const ( @@ -54,6 +56,15 @@ type ResultObject struct { Errors []string `json:"errors"` } +type ResultSensor struct { + Name string `json:"name"` + Value string `json:"value"` + State string `json:"state"` + Dev string `json:"dev"` + Units string `json:"units"` + Type string `json:"type"` +} + type Exporter struct { URI string mutex sync.Mutex @@ -64,6 +75,10 @@ type Exporter struct { up *prometheus.Desc scrapeFailures prometheus.Counter volumeOnline *prometheus.Desc + jbodStatus *prometheus.Desc + jbodTemp *prometheus.Desc + jbodVoltage *prometheus.Desc + jbodSlotStatus *prometheus.Desc } func NewExporter(uri string) *Exporter { @@ -85,6 +100,30 @@ func NewExporter(uri string) *Exporter { []string{"volume"}, nil, ), + jbodStatus: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "jbod", "status"), + "Status of JBOD.", + []string{"jbod"}, + nil, + ), + jbodTemp: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "jbod", "temp"), + "Temperature of JBOD.", + []string{"jbod", "name", "state"}, + nil, + ), + jbodVoltage: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "jbod", "voltage"), + "Voltage of JBOD.", + []string{"jbod", "name", "state"}, + nil, + ), + jbodSlotStatus: prometheus.NewDesc( + prometheus.BuildFQName(namespace, "jbod", "slot_status"), + "Status of JBOD slot.", + []string{"jbod", "slot", "state"}, + nil, + ), client: &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: *insecure}, @@ -97,6 +136,10 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { ch <- e.up e.scrapeFailures.Describe(ch) ch <- e.volumeOnline + ch <- e.jbodStatus + ch <- e.jbodTemp + ch <- e.jbodVoltage + ch <- e.jbodSlotStatus } func (e *Exporter) Collect(ch chan<- prometheus.Metric) { @@ -114,6 +157,7 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { func (e *Exporter) collect(ch chan<- prometheus.Metric) error { + // Volumes volumes, err := e.getVolumes(ch) if err != nil { err = fmt.Errorf("getVolumes(): %v", err) @@ -128,6 +172,21 @@ func (e *Exporter) collect(ch chan<- prometheus.Metric) error { } } + // JBODs + jbods, err := e.getJBODs(ch) + if err != nil { + err = fmt.Errorf("getJBODs(): %v", err) + } + + if len(jbods) > 0 { + for _, jbod := range jbods { + err = e.getJBODSensors(ch, jbod) + if err != nil { + err = fmt.Errorf("getJBODSensors(): %v", err) + } + } + } + return err } @@ -160,6 +219,52 @@ func (e *Exporter) getVolumeStatus(ch chan<- prometheus.Metric, volume string) e return err } +func (e *Exporter) getJBODs(ch chan<- prometheus.Metric) ([]string, error) { + + apiResponse, err := e.queryApi(ch, "jbod", "get_names", []string{""}); if err != nil { return nil, err } + apiResult, err := json.Marshal(apiResponse.Result); if err != nil { return nil, err } + + var jbods []string + err = json.Unmarshal([]byte(apiResult), &jbods) + + return jbods, err +} + +func (e *Exporter) getJBODSensors(ch chan<- prometheus.Metric, jbod string) error { + + apiResponse, err := e.queryApi(ch, "jbod", "get_sensors", []string{jbod}); if err != nil { return err } + apiResult, err := json.Marshal(apiResponse.Result); if err != nil { return err } + + var sensors []ResultSensor + err = json.Unmarshal([]byte(apiResult), &sensors) + + for _, sensor := range sensors { + var status float64 = 0 + if sensor.Dev == "jbod" { + switch sensor.Type { + case "state": + if sensor.State == "ok" { status = 1 } + ch <- prometheus.MustNewConstMetric(e.jbodStatus, prometheus.GaugeValue, status, jbod) + break + case "temperature": + value, _ := strconv.ParseFloat(sensor.Value, 64) + ch <- prometheus.MustNewConstMetric(e.jbodTemp, prometheus.GaugeValue, value, jbod, sensor.Name, sensor.State) + break + case "voltage": + value, _ := strconv.ParseFloat(sensor.Value, 64) + ch <- prometheus.MustNewConstMetric(e.jbodVoltage, prometheus.GaugeValue, value, jbod, sensor.Name, sensor.State) + break + } + } else { + slot := strings.Split(sensor.Dev, ":") + if sensor.State == "ok" { status = 1 } + ch <- prometheus.MustNewConstMetric(e.jbodSlotStatus, prometheus.GaugeValue, status, jbod, slot[1], sensor.State) + } + } + + return err +} + func (e *Exporter) queryApi(ch chan<- prometheus.Metric, object string, method string, params []string) (*ApiResponse, error) { reqObject := &ApiRequest{