package collector import ( "sync/atomic" "github.com/prometheus/client_golang/prometheus" ) type baseCollector struct { device string product string up *prometheus.Desc scrapeDuration *prometheus.Desc scrapeErrors *prometheus.Desc errorCount atomic.Uint64 } func newBaseCollector(device, product string) baseCollector { labels := []string{"device", "product"} return baseCollector{ device: device, product: product, up: prometheus.NewDesc( "shelly_up", "Whether the last status request to the Shelly device succeeded (1) or failed (0).", labels, nil, ), scrapeDuration: prometheus.NewDesc( "shelly_scrape_duration_seconds", "Duration of the last Shelly device status request in seconds.", labels, nil, ), scrapeErrors: prometheus.NewDesc( "shelly_scrape_errors_total", "Total number of failed Shelly device status requests.", labels, nil, ), } } func (c *baseCollector) describe(channel chan<- *prometheus.Desc) { channel <- c.up channel <- c.scrapeDuration channel <- c.scrapeErrors } func (c *baseCollector) collect(channel chan<- prometheus.Metric, success bool, durationSeconds float64) { up := float64(0) if success { up = 1 } else { c.errorCount.Add(1) } labels := []string{c.device, c.product} channel <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, up, labels...) channel <- prometheus.MustNewConstMetric(c.scrapeDuration, prometheus.GaugeValue, durationSeconds, labels...) channel <- prometheus.MustNewConstMetric(c.scrapeErrors, prometheus.CounterValue, float64(c.errorCount.Load()), labels...) }