add lite summary statistics
This commit is contained in:
parent
0be5c6d759
commit
e9b129c58c
1 changed files with 79 additions and 9 deletions
86
exporter.go
86
exporter.go
|
@ -7,36 +7,93 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
addr = flag.String("listen-address", ":9454", "The address to listen on for HTTP requests.")
|
addr = flag.String("listen-address", ":9454", "The address to listen on for HTTP requests.")
|
||||||
|
pollInterval = flag.Duration("poll-interval", 1*time.Second, "Time between executions of `lifepo4wered-cli get`")
|
||||||
|
|
||||||
lifepo4weredVars = prometheus.NewGaugeVec(
|
lifepo4weredVars = promauto.NewGaugeVec(
|
||||||
prometheus.GaugeOpts{
|
prometheus.GaugeOpts{
|
||||||
Name: "lifepo4wered",
|
Name: "lifepo4wered",
|
||||||
Help: "Variables gathered from the lifepo4wered-cli tool",
|
Help: "Variables gathered from the lifepo4wered-cli tool",
|
||||||
},
|
},
|
||||||
[]string{"var"},
|
[]string{"var"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
lifepo4weredSummaries = map[string]*liteSummary{
|
||||||
|
"VIN": newLiteSummary("voltage_in", "Voltage in (mV)"),
|
||||||
|
"VOUT": newLiteSummary("voltage_out", "Voltage out (mV)"),
|
||||||
|
"VBAT": newLiteSummary("voltage_bat", "Battery voltage (mV)"),
|
||||||
|
"IOUT": newLiteSummary("current_out", "Current out (mA)"),
|
||||||
|
}
|
||||||
|
lifepo4weredPOut = newLiteSummary("power_out", "Power out (mW)")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
type liteSummary struct {
|
||||||
prometheus.MustRegister(lifepo4weredVars)
|
mu sync.Mutex
|
||||||
|
min float64
|
||||||
|
max float64
|
||||||
|
sum float64
|
||||||
|
count int
|
||||||
|
|
||||||
|
desc *prometheus.Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
func getVars() {
|
func newLiteSummary(varName, help string) *liteSummary {
|
||||||
|
s := &liteSummary{
|
||||||
|
min: math.Inf(1),
|
||||||
|
max: math.Inf(-1),
|
||||||
|
desc: prometheus.NewDesc("lifepo4wered_"+varName, help, []string{"stat"}, nil),
|
||||||
|
}
|
||||||
|
prometheus.MustRegister(s)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *liteSummary) Describe(ch chan<- *prometheus.Desc) { ch <- s.desc }
|
||||||
|
|
||||||
|
func (s *liteSummary) Collect(ch chan<- prometheus.Metric) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
ch <- prometheus.MustNewConstMetric(s.desc, prometheus.GaugeValue, s.min, "min")
|
||||||
|
ch <- prometheus.MustNewConstMetric(s.desc, prometheus.GaugeValue, s.max, "max")
|
||||||
|
mean := s.sum
|
||||||
|
if s.count > 0 {
|
||||||
|
mean /= float64(s.count)
|
||||||
|
}
|
||||||
|
ch <- prometheus.MustNewConstMetric(s.desc, prometheus.GaugeValue, mean, "mean")
|
||||||
|
s.min = math.Inf(1)
|
||||||
|
s.max = math.Inf(-1)
|
||||||
|
s.sum, s.count = 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *liteSummary) Observe(x float64) {
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
s.min = min(s.min, x)
|
||||||
|
s.max = max(s.max, x)
|
||||||
|
s.sum += x
|
||||||
|
s.count++
|
||||||
|
}
|
||||||
|
|
||||||
|
func pollVars() {
|
||||||
cmd := exec.Command("lifepo4wered-cli", "get")
|
cmd := exec.Command("lifepo4wered-cli", "get")
|
||||||
out, err := cmd.Output()
|
out, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Couldn't execute command: %v", err)
|
log.Fatalf("Couldn't execute command: %v", err)
|
||||||
}
|
}
|
||||||
|
pout := 1
|
||||||
|
labels := prometheus.Labels{"var": ""}
|
||||||
|
|
||||||
s := bufio.NewScanner(bytes.NewReader(out))
|
s := bufio.NewScanner(bytes.NewReader(out))
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
// token space equals space number
|
// token space equals space number
|
||||||
|
@ -45,20 +102,33 @@ func getVars() {
|
||||||
if _, err := fmt.Sscanf(s.Text(), "%s = %d", &name, &num); err != nil {
|
if _, err := fmt.Sscanf(s.Text(), "%s = %d", &name, &num); err != nil {
|
||||||
log.Fatalf("Couldn't scan line: %v", err)
|
log.Fatalf("Couldn't scan line: %v", err)
|
||||||
}
|
}
|
||||||
lifepo4weredVars.With(prometheus.Labels{"var": name}).Set(float64(num))
|
labels["var"] = name
|
||||||
|
lifepo4weredVars.With(labels).Set(float64(num))
|
||||||
|
|
||||||
|
v, ok := lifepo4weredSummaries[name]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.Observe(float64(num))
|
||||||
|
switch name {
|
||||||
|
case "VOUT", "IOUT":
|
||||||
|
pout *= num
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := s.Err(); err != nil {
|
if err := s.Err(); err != nil {
|
||||||
log.Fatalf("Couldn't scan output: %v", err)
|
log.Fatalf("Couldn't scan output: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lifepo4weredPOut.Observe(float64(pout) / 1e3) // mV * mA = µW; 1000µW = 1mW.
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
getVars()
|
pollVars()
|
||||||
go func() {
|
go func() {
|
||||||
for range time.Tick(15 * time.Second) {
|
for range time.Tick(*pollInterval) {
|
||||||
getVars()
|
pollVars()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue