Add prom exporter

This commit is contained in:
Josh Deprez 2024-09-27 12:50:13 +10:00
parent 2c99912a8a
commit 3b53190410
3 changed files with 93 additions and 10 deletions

View file

@ -9,6 +9,8 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"log"
"net/http"
"os" "os"
"os/signal" "os/signal"
"regexp" "regexp"
@ -16,6 +18,10 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
"periph.io/x/conn/v3/i2c/i2creg" "periph.io/x/conn/v3/i2c/i2creg"
"periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/physic"
"periph.io/x/devices/v3/ina219" "periph.io/x/devices/v3/ina219"
@ -26,8 +32,9 @@ func mainImpl() error {
if _, err := host.Init(); err != nil { if _, err := host.Init(); err != nil {
return err return err
} }
address := flag.Int("address", 0x45, "I²C address") httpAddr := flag.String("http-address", ":9455", "Listen addr for HTTP handler")
i2cbus := flag.String("bus", "", "I²C bus (/dev/i2c-1)") i2cAddress := flag.Int("i2c-address", 0x45, "I²C address")
i2cBus := flag.String("i2c-bus", "", "I²C bus (/dev/i2c-1)")
senseResistor := flag.String("sense-resistor", "10m", "Resistance of the shunt resistor in ohms (optionally with suffix m = milli, {µ,mu} = micro, n = nano)") senseResistor := flag.String("sense-resistor", "10m", "Resistance of the shunt resistor in ohms (optionally with suffix m = milli, {µ,mu} = micro, n = nano)")
maxCurrent := flag.String("max-current", "8", "Maximum current through the device in amps (optional suffix as for --sense-resistor)") maxCurrent := flag.String("max-current", "8", "Maximum current through the device in amps (optional suffix as for --sense-resistor)")
@ -53,14 +60,14 @@ func mainImpl() error {
} }
// Open default I²C bus. // Open default I²C bus.
bus, err := i2creg.Open(*i2cbus) bus, err := i2creg.Open(*i2cBus)
if err != nil { if err != nil {
return fmt.Errorf("failed to open I²C: %v", err) return fmt.Errorf("failed to open I²C: %v", err)
} }
defer bus.Close() defer bus.Close()
sensor, err := ina219.New(bus, &ina219.Opts{ sensor, err := ina219.New(bus, &ina219.Opts{
Address: *address, Address: *i2cAddress,
SenseResistor: resistor, SenseResistor: resistor,
MaxCurrent: current, MaxCurrent: current,
}) })
@ -68,13 +75,51 @@ func mainImpl() error {
return fmt.Errorf("failed to open new sensor: %v", err) return fmt.Errorf("failed to open new sensor: %v", err)
} }
constLabels := prometheus.Labels{"i2c-addr": fmt.Sprintf("0x%x", *i2cAddress)}
busVoltageHist := promauto.NewHistogram(prometheus.HistogramOpts{
Namespace: "ina219",
Name: "bus_voltage",
Help: "Bus voltage (V)",
ConstLabels: constLabels,
NativeHistogramBucketFactor: 1.001,
NativeHistogramZeroThreshold: 0.001,
})
busCurrentHist := promauto.NewHistogram(prometheus.HistogramOpts{
Namespace: "ina219",
Name: "bus_current",
Help: "Bus current (A)",
ConstLabels: constLabels,
NativeHistogramBucketFactor: 1.001,
NativeHistogramZeroThreshold: 0.001,
})
busPowerHist := promauto.NewHistogram(prometheus.HistogramOpts{
Namespace: "ina219",
Name: "bus_power",
Help: "Bus power (W)",
ConstLabels: constLabels,
NativeHistogramBucketFactor: 1.001,
NativeHistogramZeroThreshold: 0.001,
})
shuntVoltageHist := promauto.NewHistogram(prometheus.HistogramOpts{
Namespace: "ina219",
Name: "shunt_voltage",
Help: "Shunt voltage (V)",
ConstLabels: constLabels,
NativeHistogramBucketFactor: 1.001,
NativeHistogramZeroThreshold: 0.001,
})
go func() {
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(*httpAddr, nil))
}()
// Read values from sensor every second. // Read values from sensor every second.
everySecond := time.NewTicker(time.Second).C everySecond := time.NewTicker(time.Second).C
var halt = make(chan os.Signal, 1) halt := make(chan os.Signal, 1)
signal.Notify(halt, syscall.SIGTERM) signal.Notify(halt, syscall.SIGTERM)
signal.Notify(halt, syscall.SIGINT) signal.Notify(halt, syscall.SIGINT)
fmt.Println("ctrl+c to exit")
for { for {
select { select {
case <-everySecond: case <-everySecond:
@ -82,7 +127,11 @@ func mainImpl() error {
if err != nil { if err != nil {
return fmt.Errorf("sensor reading error: %v", err) return fmt.Errorf("sensor reading error: %v", err)
} }
fmt.Println(p) busVoltageHist.Observe(float64(p.Voltage) / float64(physic.Volt))
busCurrentHist.Observe(float64(p.Current) / float64(physic.Ampere))
busPowerHist.Observe(float64(p.Power) / float64(physic.Watt))
shuntVoltageHist.Observe(float64(p.Shunt) / float64(physic.Volt))
case <-halt: case <-halt:
return nil return nil
} }

14
go.mod
View file

@ -3,8 +3,20 @@ module gitea.drjosh.dev/josh/ina219-exporter
go 1.23.1 go 1.23.1
require ( require (
github.com/dustin/go-humanize v1.0.1 github.com/prometheus/client_golang v1.20.4
periph.io/x/conn/v3 v3.7.1 periph.io/x/conn/v3 v3.7.1
periph.io/x/devices/v3 v3.7.1 periph.io/x/devices/v3 v3.7.1
periph.io/x/host/v3 v3.8.2 periph.io/x/host/v3 v3.8.2
) )
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/sys v0.22.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)

26
go.sum
View file

@ -1,7 +1,29 @@
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4=
github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
periph.io/x/conn/v3 v3.7.1 h1:tMjNv3WO8jEz/ePuXl7y++2zYi8LsQ5otbmqGKy3Myg= periph.io/x/conn/v3 v3.7.1 h1:tMjNv3WO8jEz/ePuXl7y++2zYi8LsQ5otbmqGKy3Myg=
periph.io/x/conn/v3 v3.7.1/go.mod h1:c+HCVjkzbf09XzcqZu/t+U8Ss/2QuJj0jgRF6Nye838= periph.io/x/conn/v3 v3.7.1/go.mod h1:c+HCVjkzbf09XzcqZu/t+U8Ss/2QuJj0jgRF6Nye838=
periph.io/x/devices/v3 v3.7.1 h1:BsExlfYJlZUZoawzpMF7ksgC9f1eBAdqvKRCGvb+VYw= periph.io/x/devices/v3 v3.7.1 h1:BsExlfYJlZUZoawzpMF7ksgC9f1eBAdqvKRCGvb+VYw=