commit 693c125d65c3d1af1ddc4c8787ff2f648b32e47a
Author: Paco Esteban <paco@e1e0.net>
Date: Thu, 19 Dec 2019 18:20:54 +0100
initial commit
Diffstat:
A | .gitignore | | | 1 | + |
A | Makefile | | | 21 | +++++++++++++++++++++ |
A | go.mod | | | 3 | +++ |
A | main.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))
+}