prometheus-upsc-exporter

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

commit 693c125d65c3d1af1ddc4c8787ff2f648b32e47a
Author: Paco Esteban <paco@e1e0.net>
Date:   Thu, 19 Dec 2019 18:20:54 +0100

initial commit

Diffstat:
A.gitignore | 1+
AMakefile | 21+++++++++++++++++++++
Ago.mod | 3+++
Amain.go | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +upsc-exporter diff --git a/Makefile b/Makefile @@ -0,0 +1,21 @@ +BINARY=upsc-exporter + +VERSION=v0.1.0 +BUILD=`git rev-parse --short HEAD` +OS=`uname | tr "[:upper:]" "[:lower:]"` +ARCH="amd64" + +LDFLAGS=-ldflags "-X main.Version=${VERSION} -X main.Build=${BUILD} -w" + +.DEFAULT: ${BINARY} + +${BINARY}: main.go + @echo "Build for ${OS}(${ARCH}) static" + GOOS=${OS} GOARCH=${ARCH} CGO_ENABLED=0 GO111MODULE=on \ + go build ${LDFLAGS} -tags netgo -o ${BINARY} + +.PHONY: clean +clean: + rm -rf ${BINARY} + +# vim:ft=make diff --git a/go.mod b/go.mod @@ -0,0 +1,3 @@ +module git.e1e0.net/prometheus-upsc-exporter + +go 1.13 diff --git a/main.go b/main.go @@ -0,0 +1,94 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "log" + "net/http" + "os" + "os/exec" + "strconv" + "strings" +) + +type metric struct { + name string + value float64 +} + +var ( + Version string + Build string + ups *string +) + +func getMetrics(w http.ResponseWriter, r *http.Request) { + var message string + + cmd := exec.Command("upsc", *ups) + stdout, err := cmd.StdoutPipe() + if err != nil { + message = "error piping stdout" + log.Println(message) + http.Error(w, message, http.StatusInternalServerError) + return + } + if err := cmd.Start(); err != nil { + message = "error executing command" + log.Println(message) + http.Error(w, message, http.StatusInternalServerError) + return + } + + metrics := []metric{} + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + parts := strings.Split(scanner.Text(), ": ") + var value float64 = -1 + + // if we can conver to float assign a value + // if not, just check for ups status (OL || OB) + i, err := strconv.ParseFloat(parts[1], 64) + if err != nil { + if parts[1] == "OL" { + value = 0 + } + if parts[1] == "OB" { + value = 1 + } + } else { + value = i + } + + // discard everything else (also, do not need driver info). + if value >= 0 && !strings.HasPrefix(parts[0], "driver") { + metrics = append(metrics, metric{name: parts[0], value: value}) + } + } + if err := scanner.Err(); err != nil { + message = "error scanning command output" + log.Println(message) + http.Error(w, message, http.StatusInternalServerError) + return + } + + for _, m := range metrics { + fmt.Fprintf(w, "upsc_%s %.2f\n", strings.ReplaceAll(m.name, ".", "_"), m.value) + } +} + +func main() { + ups = flag.String("ups", "ups@localhost", "ups to get info from") + ver := flag.Bool("v", false, "Shows version and exists") + port := flag.Int("p", 8081, "Port to listen to") + flag.Parse() + + if *ver { + fmt.Printf("%s (%s)\n", Version, Build) + os.Exit(0) + } + + http.HandleFunc("/metrics", getMetrics) + log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*port), nil)) +}