prometheus-upsc-exporter

rather basic upsc prometheus exporter
git clone https://git.e1e0.net/prometheus-upsc-exporter.git
Log | Files | Refs | README | LICENSE

main.go (2046B)


      1 package main
      2 
      3 import (
      4 	"bufio"
      5 	"flag"
      6 	"fmt"
      7 	"log"
      8 	"net/http"
      9 	"os"
     10 	"os/exec"
     11 	"strconv"
     12 	"strings"
     13 )
     14 
     15 type metric struct {
     16 	name  string
     17 	value float64
     18 }
     19 
     20 var (
     21 	Version string
     22 	Build   string
     23 	ups     *string
     24 )
     25 
     26 func getMetrics(w http.ResponseWriter, r *http.Request) {
     27 	var message string
     28 
     29 	cmd := exec.Command("upsc", *ups)
     30 	stdout, err := cmd.StdoutPipe()
     31 	if err != nil {
     32 		message = "error piping stdout"
     33 		log.Println(message)
     34 		http.Error(w, message, http.StatusInternalServerError)
     35 		return
     36 	}
     37 	if err := cmd.Start(); err != nil {
     38 		message = "error executing command"
     39 		log.Println(message)
     40 		http.Error(w, message, http.StatusInternalServerError)
     41 		return
     42 	}
     43 
     44 	metrics := []metric{}
     45 	scanner := bufio.NewScanner(stdout)
     46 	for scanner.Scan() {
     47 		parts := strings.Split(scanner.Text(), ": ")
     48 		var value float64 = -1
     49 
     50 		// if we can conver to float assign a value
     51 		// if not, just check for ups status (OL || OB)
     52 		i, err := strconv.ParseFloat(parts[1], 64)
     53 		if err != nil {
     54 			if parts[1] == "OL" {
     55 				value = 0
     56 			}
     57 			if parts[1] == "OB" {
     58 				value = 1
     59 			}
     60 		} else {
     61 			value = i
     62 		}
     63 
     64 		// discard everything else (also, do not need driver info).
     65 		if value >= 0 && !strings.HasPrefix(parts[0], "driver") {
     66 			metrics = append(metrics, metric{name: parts[0], value: value})
     67 		}
     68 	}
     69 	if err := scanner.Err(); err != nil {
     70 		message = "error scanning command output"
     71 		log.Println(message)
     72 		http.Error(w, message, http.StatusInternalServerError)
     73 		return
     74 	}
     75 
     76 	for _, m := range metrics {
     77 		fmt.Fprintf(w, "upsc_%s %.2f\n", strings.ReplaceAll(m.name, ".", "_"), m.value)
     78 	}
     79 	cmd.Wait() // needed to close the pipe and release the child process
     80 }
     81 
     82 func main() {
     83 	ups = flag.String("ups", "ups@localhost", "ups to get info from")
     84 	ver := flag.Bool("v", false, "Shows version and exists")
     85 	port := flag.Int("p", 8081, "Port to listen to")
     86 	flag.Parse()
     87 
     88 	if *ver {
     89 		fmt.Printf("%s (%s)\n", Version, Build)
     90 		os.Exit(0)
     91 	}
     92 
     93 	http.HandleFunc("/metrics", getMetrics)
     94 	log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*port), nil))
     95 }