package loadavg import ( "context" "fmt" "os" "strconv" "strings" "time" "git.faercol.me/monitoring/sys-exporter/registry" "github.com/prometheus/client_golang/prometheus" ) const loadAvgFileLocation = "/proc/loadavg" type LoadAvgCollector struct { loadAvgFileLocation string promExporter *prometheus.SummaryVec updateFreq time.Duration } func (c *LoadAvgCollector) Collect() interface{} { return nil } func (c *LoadAvgCollector) update() error { fileContent, err := os.ReadFile(c.loadAvgFileLocation) if err != nil { return fmt.Errorf("failed to read loadavg file: %w", err) } vals := strings.Split(string(fileContent), " ") if len(vals) != 5 { return fmt.Errorf("invalid format %q for loadavg file", string(fileContent)) } var load1Min, load5Min, load15Min float64 if load1Min, err = strconv.ParseFloat(vals[0], 64); err != nil { return fmt.Errorf("invalid value %q for load 1min: %w", vals[0], err) } if load5Min, err = strconv.ParseFloat(vals[1], 64); err != nil { return fmt.Errorf("invalid value %q for load 5mins: %w", vals[1], err) } if load15Min, err = strconv.ParseFloat(vals[2], 64); err != nil { return fmt.Errorf("invalid value %q for load 15min: %w", vals[2], err) } c.promExporter.WithLabelValues("1min").Observe(load1Min) c.promExporter.WithLabelValues("5mins").Observe(load5Min) c.promExporter.WithLabelValues("15mins").Observe(load15Min) return nil } func (c *LoadAvgCollector) Run(ctx context.Context) { if err := c.update(); err != nil { fmt.Printf("Failed to init loadavg collector: %s\n", err) } for { select { case <-ctx.Done(): return case <-time.After(c.updateFreq): if err := c.update(); err != nil { fmt.Printf("Failed to update loadavg collector: %s\n", err) } } } } func (c *LoadAvgCollector) PromCollector() prometheus.Collector { return c.promExporter } func New() *LoadAvgCollector { return &LoadAvgCollector{ updateFreq: 1 * time.Second, loadAvgFileLocation: loadAvgFileLocation, promExporter: prometheus.NewSummaryVec(prometheus.SummaryOpts{Namespace: "system", Name: "loadavg", Help: "Load average of the system"}, []string{"period"}), } } func init() { registry.R.MustRegisterCollector("system.loadavg", New()) }