prusa-connect-exporter/main.go

131 lines
3.4 KiB
Go

package main
import (
"context"
"encoding/json"
"flag"
"io"
"log"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
type Metrics struct {
TempNozzle int `json:"temp_nozzle"`
TempBed int `json:"temp_bed"`
Material string `json:"material"`
ZPosition float64 `json:"pos_z_mm"`
PrintingSpeed int `json:"printing_speed"`
FlowFactor int `json:"flow_factor"`
}
type Config struct {
QueryHostname string
QueryInterval int
Port string
Path string
}
var (
opsFlowFactor = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "prusa_connect",
Name: "flow_factor",
Help: "Current flow factor, as a percentage",
})
opsPrintSpeed = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "prusa_connect",
Name: "printing_speed",
Help: "Current print speed, as a percentage",
})
opsZPosition = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "prusa_connect",
Name: "z_position",
Help: "Depth, in MM, of the Z head",
})
opsBed = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "prusa_connect",
Name: "temp_bed",
Help: "Temperature, in celsius, of the print bed",
})
opsNozzle = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "prusa_connect",
Name: "temp_nozzle",
Help: "Temperature, in celsius, of the print nozzle",
})
)
func recordMetrics(ctx context.Context, config Config) {
go func() {
for {
select {
case <-ctx.Done():
log.Print("exiting!")
return
default:
time.Sleep(time.Second * time.Duration(config.QueryInterval))
res, err := http.Get(config.QueryHostname + "/api/telemetry")
if err != nil {
log.Printf("error retrieving telemetry: %v", err)
break
}
b, err := io.ReadAll(res.Body)
if err != nil {
log.Printf("error retrieving telemetry: %v", err)
break
}
t := &Metrics{}
err = json.Unmarshal(b, t)
if err != nil {
log.Printf("error parsing telemetry: %v", err)
break
}
opsFlowFactor.Set(float64(t.FlowFactor))
opsPrintSpeed.Set(float64(t.PrintingSpeed))
opsZPosition.Set(t.ZPosition)
opsBed.Set(float64(t.TempBed))
opsNozzle.Set(float64(t.TempNozzle))
}
}
}()
}
func main() {
var hostname string
flag.StringVar(&hostname, "hostname", "localhost", "Hostname the Prusa Connect API is available at (assumes http)")
var queryInterval int
flag.IntVar(&queryInterval, "interval", 2, "How often, in seconds, to query the API")
var port string
flag.StringVar(&port, "port", "2112", "Local port to export metrics on")
var path string
flag.StringVar(&path, "path", "metrics", "Local path to export metrics on")
flag.Parse()
if queryInterval < 1 {
log.Fatalf("query interval must be greater than 0; %d received", queryInterval)
}
config := Config{
QueryHostname: "http://" + hostname,
QueryInterval: queryInterval,
Port: port,
Path: path,
}
r := prometheus.NewRegistry()
r.MustRegister(opsNozzle)
r.MustRegister(opsBed)
r.MustRegister(opsZPosition)
r.MustRegister(opsPrintSpeed)
r.MustRegister(opsFlowFactor)
recordMetrics(context.Background(), config)
log.Printf("starting exporter on :%v", config.Port)
http.Handle("/"+config.Path, promhttp.HandlerFor(r, promhttp.HandlerOpts{}))
http.ListenAndServe(":"+config.Port, nil)
}