upgrade in prep for PC 4.4.0
This commit is contained in:
		
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					# Prusa Connect Prometheus Exporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version v0.1.0 of this exporter supports the pre-4.4.0 changes to the Prusa Connect API (non-API-key version).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Current master branch supports the new, 4.4.0-beta2 release of Prusa Connect as well as the older API.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`./prusa-connect-exporter -h`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `apikey`
 | 
				
			||||||
 | 
					    Prusa Connect API key (see Main Menu -> Settings -> Network on the printer).
 | 
				
			||||||
 | 
					    If no key is provided, exporter assumes the older API layout when querying the printer.
 | 
				
			||||||
 | 
					* `hostname`
 | 
				
			||||||
 | 
					    Hostname the Prusa Connect API is available at (assumes http) (default "localhost")
 | 
				
			||||||
 | 
					* `interval`
 | 
				
			||||||
 | 
					    How often, in seconds, to query the API (default 2)
 | 
				
			||||||
 | 
					* `path`
 | 
				
			||||||
 | 
					    Local path to export metrics on (default "metrics")
 | 
				
			||||||
 | 
					* `port`
 | 
				
			||||||
 | 
					    Local port to export metrics on (default "2112")
 | 
				
			||||||
							
								
								
									
										321
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										321
									
								
								main.go
									
									
									
									
									
								
							@@ -15,7 +15,8 @@ import (
 | 
				
			|||||||
	"github.com/prometheus/client_golang/prometheus/promhttp"
 | 
						"github.com/prometheus/client_golang/prometheus/promhttp"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Metrics struct {
 | 
					// original /api/telemetry type struct
 | 
				
			||||||
 | 
					type MetricsV1 struct {
 | 
				
			||||||
	TempNozzle    int     `json:"temp_nozzle"`
 | 
						TempNozzle    int     `json:"temp_nozzle"`
 | 
				
			||||||
	TempBed       int     `json:"temp_bed"`
 | 
						TempBed       int     `json:"temp_bed"`
 | 
				
			||||||
	Material      string  `json:"material"`
 | 
						Material      string  `json:"material"`
 | 
				
			||||||
@@ -29,68 +30,135 @@ type Metrics struct {
 | 
				
			|||||||
	ProjectName   string  `json:"project_name"`
 | 
						ProjectName   string  `json:"project_name"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// new 4.4.0+ /api/printer struct
 | 
				
			||||||
 | 
					type MetricsV2 struct {
 | 
				
			||||||
 | 
						Telemetry   Telemetry   `json:"telemetry"`
 | 
				
			||||||
 | 
						Temperature Temperature `json:"temperature"`
 | 
				
			||||||
 | 
						State       State       `json:"state"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Telemetry struct {
 | 
				
			||||||
 | 
						TempBed    float64 `json:"temp-bed"`
 | 
				
			||||||
 | 
						TempNozzle float64 `json:"temp-nozzle"`
 | 
				
			||||||
 | 
						PrintSpeed int     `json:"print-speed"`
 | 
				
			||||||
 | 
						ZHeight    float64 `json:"z-height"`
 | 
				
			||||||
 | 
						Material   string  `json:"material"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Temperature struct {
 | 
				
			||||||
 | 
						Tool0 Tempatures `json:"tool0"`
 | 
				
			||||||
 | 
						Bed   Tempatures `json:"bed"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Tempatures struct {
 | 
				
			||||||
 | 
						Actual  float64 `json:"actual"`
 | 
				
			||||||
 | 
						Target  float64 `json:"target"`
 | 
				
			||||||
 | 
						Display float64 `json:"display"`
 | 
				
			||||||
 | 
						Offset  float64 `json:"offset"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type State struct {
 | 
				
			||||||
 | 
						Text  string `json:"text"`
 | 
				
			||||||
 | 
						Flags Flags  `json:"flags"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Flags struct {
 | 
				
			||||||
 | 
						Operational   bool `json:"operational"`
 | 
				
			||||||
 | 
						Paused        bool `json:"paused"`
 | 
				
			||||||
 | 
						Printing      bool `json:"printing"`
 | 
				
			||||||
 | 
						Cancelling    bool `json:"cancelling"`
 | 
				
			||||||
 | 
						Pausing       bool `json:"pausing"`
 | 
				
			||||||
 | 
						SdReady       bool `json:"sdReady"`
 | 
				
			||||||
 | 
						Error         bool `json:"error"`
 | 
				
			||||||
 | 
						ClosedOnError bool `json:"closedOnError"`
 | 
				
			||||||
 | 
						Ready         bool `json:"ready"`
 | 
				
			||||||
 | 
						Busy          bool `json:"busy"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// /api/job struct
 | 
				
			||||||
 | 
					type JobV2 struct {
 | 
				
			||||||
 | 
						State    string   `json:"state"`
 | 
				
			||||||
 | 
						Job      Job      `json:"job"`
 | 
				
			||||||
 | 
						Progress Progress `json:"progress"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type File struct {
 | 
				
			||||||
 | 
						Name    string `json:"name"`
 | 
				
			||||||
 | 
						Path    string `json:"path"`
 | 
				
			||||||
 | 
						Display string `json:"display"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Job struct {
 | 
				
			||||||
 | 
						EstimatedPrintTime int  `json:"estimatedPrintTime"`
 | 
				
			||||||
 | 
						File               File `json:"file"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Progress struct {
 | 
				
			||||||
 | 
						Completion    float64 `json:"completion"`
 | 
				
			||||||
 | 
						PrintTime     int     `json:"printTime"`
 | 
				
			||||||
 | 
						PrintTimeLeft int     `json:"printTimeLeft"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Config struct {
 | 
					type Config struct {
 | 
				
			||||||
	QueryHostname string
 | 
						QueryHostname string
 | 
				
			||||||
	QueryInterval int
 | 
						QueryInterval int
 | 
				
			||||||
	Port          string
 | 
						Port          string
 | 
				
			||||||
	Path          string
 | 
						Path          string
 | 
				
			||||||
 | 
						APIKey        string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	opsFlowFactor = prometheus.NewGauge(prometheus.GaugeOpts{
 | 
					 | 
				
			||||||
		Namespace: "prusa_connect",
 | 
					 | 
				
			||||||
		Name:      "flow_factor",
 | 
					 | 
				
			||||||
		Help:      "Current flow factor, as a unitless number",
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	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:      "Vertical 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",
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	opsProgress = prometheus.NewGauge(prometheus.GaugeOpts{
 | 
					 | 
				
			||||||
		Namespace: "prusa_connect",
 | 
					 | 
				
			||||||
		Name:      "progress",
 | 
					 | 
				
			||||||
		Help:      "Current print completeness, as a percentage",
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	opsDuration = prometheus.NewGauge(prometheus.GaugeOpts{
 | 
					 | 
				
			||||||
		Namespace: "prusa_connect",
 | 
					 | 
				
			||||||
		Name:      "duration",
 | 
					 | 
				
			||||||
		Help:      "Duration of current print job, as seconds since start",
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	opsRemaining = prometheus.NewGauge(prometheus.GaugeOpts{
 | 
					 | 
				
			||||||
		Namespace: "prusa_connect",
 | 
					 | 
				
			||||||
		Name:      "remaining",
 | 
					 | 
				
			||||||
		Help:      "Estimated remaining time of current print job, as seconds",
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	errCount = 0
 | 
						errCount = 0
 | 
				
			||||||
 | 
						gauges   = map[string]prometheus.Gauge{
 | 
				
			||||||
 | 
							"flow_factor": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "flow_factor",
 | 
				
			||||||
 | 
								Help:      "Current flow factor, as a unitless number",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"printing_speed": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "printing_speed",
 | 
				
			||||||
 | 
								Help:      "Current print speed, as a percentage",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"z_position": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "z_position",
 | 
				
			||||||
 | 
								Help:      "Vertical depth, in mm, of the Z head",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"temp_bed": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "temp_bed",
 | 
				
			||||||
 | 
								Help:      "Temperature, in celsius, of the print bed",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"temp_nozzle": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "temp_nozzle",
 | 
				
			||||||
 | 
								Help:      "Temperature, in celsius, of the print nozzle",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"progress": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "progress",
 | 
				
			||||||
 | 
								Help:      "Current print completeness, as a percentage",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"duration": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "duration",
 | 
				
			||||||
 | 
								Help:      "Duration of current print job, as seconds since start",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							"remaining": prometheus.NewGauge(prometheus.GaugeOpts{
 | 
				
			||||||
 | 
								Namespace: "prusa_connect",
 | 
				
			||||||
 | 
								Name:      "remaining",
 | 
				
			||||||
 | 
								Help:      "Estimated remaining time of current print job, as seconds",
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func errLog(err error) {
 | 
					func errLog(err error) {
 | 
				
			||||||
	errCount++
 | 
						errCount++
 | 
				
			||||||
	// reset metrics
 | 
						// reset metrics
 | 
				
			||||||
	opsFlowFactor.Set(0)
 | 
						for _, g := range gauges {
 | 
				
			||||||
	opsPrintSpeed.Set(0)
 | 
							g.Set(0)
 | 
				
			||||||
	opsZPosition.Set(0)
 | 
						}
 | 
				
			||||||
	opsBed.Set(0)
 | 
					 | 
				
			||||||
	opsNozzle.Set(0)
 | 
					 | 
				
			||||||
	opsProgress.Set(0)
 | 
					 | 
				
			||||||
	opsDuration.Set(0)
 | 
					 | 
				
			||||||
	opsRemaining.Set(0)
 | 
					 | 
				
			||||||
	if errCount == 5 {
 | 
						if errCount == 5 {
 | 
				
			||||||
		log.Printf("suppressing further error logging")
 | 
							log.Printf("suppressing further error logging")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -109,42 +177,124 @@ func recordMetrics(ctx context.Context, config Config) {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				time.Sleep(time.Second * time.Duration(config.QueryInterval))
 | 
									time.Sleep(time.Second * time.Duration(config.QueryInterval))
 | 
				
			||||||
				res, err := http.Get(config.QueryHostname + "/api/telemetry")
 | 
									if config.APIKey == "" {
 | 
				
			||||||
				if err != nil {
 | 
										parseMetricsV1(ctx, config)
 | 
				
			||||||
					errLog(err)
 | 
					 | 
				
			||||||
					break
 | 
										break
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				b, err := io.ReadAll(res.Body)
 | 
									parseMetricsV2(ctx, config)
 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					errLog(err)
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				t := &Metrics{}
 | 
					 | 
				
			||||||
				err = json.Unmarshal(b, t)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					errLog(err)
 | 
					 | 
				
			||||||
					break
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if errCount != 0 {
 | 
					 | 
				
			||||||
					log.Printf("connection established")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				errCount = 0
 | 
					 | 
				
			||||||
				opsFlowFactor.Set(float64(t.FlowFactor))
 | 
					 | 
				
			||||||
				opsPrintSpeed.Set(float64(t.PrintingSpeed))
 | 
					 | 
				
			||||||
				opsZPosition.Set(t.ZPosition)
 | 
					 | 
				
			||||||
				opsBed.Set(float64(t.TempBed))
 | 
					 | 
				
			||||||
				opsNozzle.Set(float64(t.TempNozzle))
 | 
					 | 
				
			||||||
				opsProgress.Set(float64(t.Progress))
 | 
					 | 
				
			||||||
				opsDuration.Set(float64(parseDuration(t.PrintDur) / time.Second))
 | 
					 | 
				
			||||||
				estimatedTimeRemaining, err := strconv.ParseFloat(t.TimeEst, 64)
 | 
					 | 
				
			||||||
				if err == nil {
 | 
					 | 
				
			||||||
					opsRemaining.Set(float64(estimatedTimeRemaining))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseMetricsV1(ctx context.Context, config Config) {
 | 
				
			||||||
 | 
						t, err := getTelemetry(config.QueryHostname)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							errLog(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if errCount != 0 {
 | 
				
			||||||
 | 
							errCount = 0
 | 
				
			||||||
 | 
							log.Printf("connection established")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gauges["flow_factor"].Set(float64(t.FlowFactor))
 | 
				
			||||||
 | 
						gauges["printing_speed"].Set(float64(t.PrintingSpeed))
 | 
				
			||||||
 | 
						gauges["z_position"].Set(t.ZPosition)
 | 
				
			||||||
 | 
						gauges["temp_bed"].Set(float64(t.TempBed))
 | 
				
			||||||
 | 
						gauges["temp_nozzle"].Set(float64(t.TempNozzle))
 | 
				
			||||||
 | 
						gauges["progress"].Set(float64(t.Progress))
 | 
				
			||||||
 | 
						gauges["duration"].Set(float64(parseDuration(t.PrintDur) / time.Second))
 | 
				
			||||||
 | 
						estimatedTimeRemaining, err := strconv.ParseFloat(t.TimeEst, 64)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							gauges["remaining"].Set(float64(estimatedTimeRemaining))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseMetricsV2(ctx context.Context, config Config) {
 | 
				
			||||||
 | 
						t, err := getPrinter(config.Port, config.APIKey)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							errLog(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						j, err := getJob(config.Port, config.APIKey)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							errLog(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if errCount != 0 {
 | 
				
			||||||
 | 
							errCount = 0
 | 
				
			||||||
 | 
							log.Printf("connection established")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gauges["printing_speed"].Set(float64(t.Telemetry.PrintSpeed))
 | 
				
			||||||
 | 
						gauges["z_position"].Set(t.Telemetry.ZHeight)
 | 
				
			||||||
 | 
						gauges["temp_bed"].Set(float64(t.Telemetry.TempBed))
 | 
				
			||||||
 | 
						gauges["temp_nozzle"].Set(float64(t.Telemetry.TempNozzle))
 | 
				
			||||||
 | 
						gauges["progress"].Set(float64(j.Progress.Completion) * 100)
 | 
				
			||||||
 | 
						gauges["duration"].Set(float64(j.Progress.PrintTime))
 | 
				
			||||||
 | 
						gauges["remaining"].Set(float64(j.Progress.PrintTimeLeft))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getJob(hostname, apiKey string) (*JobV2, error) {
 | 
				
			||||||
 | 
						r, err := http.NewRequest(http.MethodGet, hostname+"/api/job", nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &JobV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r.Header.Set("X-Api-Key", apiKey)
 | 
				
			||||||
 | 
						res, err := http.DefaultClient.Do(r)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &JobV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						b, err := io.ReadAll(res.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &JobV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						j := &JobV2{}
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, j)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &JobV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return j, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getPrinter(hostname, apiKey string) (*MetricsV2, error) {
 | 
				
			||||||
 | 
						r, err := http.NewRequest(http.MethodGet, hostname+"/api/printer", nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						r.Header.Set("X-Api-Key", apiKey)
 | 
				
			||||||
 | 
						res, err := http.DefaultClient.Do(r)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						b, err := io.ReadAll(res.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						j := &MetricsV2{}
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, j)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV2{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return j, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getTelemetry(hostname string) (*MetricsV1, error) {
 | 
				
			||||||
 | 
						res, err := http.Get(hostname + "/api/telemetry")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV1{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						b, err := io.ReadAll(res.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV1{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t := &MetricsV1{}
 | 
				
			||||||
 | 
						err = json.Unmarshal(b, t)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return &MetricsV1{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return t, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// taking a guess on proper parsing here...
 | 
					// taking a guess on proper parsing here...
 | 
				
			||||||
func parseDuration(d string) time.Duration {
 | 
					func parseDuration(d string) time.Duration {
 | 
				
			||||||
	dur := 0
 | 
						dur := 0
 | 
				
			||||||
@@ -187,6 +337,8 @@ func main() {
 | 
				
			|||||||
	flag.StringVar(&port, "port", "2112", "Local port to export metrics on")
 | 
						flag.StringVar(&port, "port", "2112", "Local port to export metrics on")
 | 
				
			||||||
	var path string
 | 
						var path string
 | 
				
			||||||
	flag.StringVar(&path, "path", "metrics", "Local path to export metrics on")
 | 
						flag.StringVar(&path, "path", "metrics", "Local path to export metrics on")
 | 
				
			||||||
 | 
						var apiKey string
 | 
				
			||||||
 | 
						flag.StringVar(&apiKey, "apikey", "", "Prusa Connect API key (see Main Menu -> Settings -> Network on the printer)")
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if queryInterval < 1 {
 | 
						if queryInterval < 1 {
 | 
				
			||||||
@@ -198,18 +350,13 @@ func main() {
 | 
				
			|||||||
		QueryInterval: queryInterval,
 | 
							QueryInterval: queryInterval,
 | 
				
			||||||
		Port:          port,
 | 
							Port:          port,
 | 
				
			||||||
		Path:          path,
 | 
							Path:          path,
 | 
				
			||||||
 | 
							APIKey:        apiKey,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r := prometheus.NewRegistry()
 | 
						r := prometheus.NewRegistry()
 | 
				
			||||||
	r.MustRegister(opsNozzle)
 | 
						for _, g := range gauges {
 | 
				
			||||||
	r.MustRegister(opsBed)
 | 
							r.MustRegister(g)
 | 
				
			||||||
	r.MustRegister(opsZPosition)
 | 
						}
 | 
				
			||||||
	r.MustRegister(opsPrintSpeed)
 | 
					 | 
				
			||||||
	r.MustRegister(opsFlowFactor)
 | 
					 | 
				
			||||||
	r.MustRegister(opsProgress)
 | 
					 | 
				
			||||||
	r.MustRegister(opsDuration)
 | 
					 | 
				
			||||||
	r.MustRegister(opsRemaining)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	recordMetrics(context.Background(), config)
 | 
						recordMetrics(context.Background(), config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Printf("starting exporter on :%v", config.Port)
 | 
						log.Printf("starting exporter on :%v", config.Port)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user