-
Notifications
You must be signed in to change notification settings - Fork 149
/
cpus.go
102 lines (89 loc) · 2.89 KB
/
cpus.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/* Copyright 2017 Victor Penso, Matteo Dessalvi
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package main
import (
"github.com/prometheus/client_golang/prometheus"
"io/ioutil"
"log"
"os/exec"
"strconv"
"strings"
)
type CPUsMetrics struct {
alloc float64
idle float64
other float64
total float64
}
func CPUsGetMetrics() *CPUsMetrics {
return ParseCPUsMetrics(CPUsData())
}
func ParseCPUsMetrics(input []byte) *CPUsMetrics {
var cm CPUsMetrics
if strings.Contains(string(input), "/") {
splitted := strings.Split(strings.TrimSpace(string(input)), "/")
cm.alloc, _ = strconv.ParseFloat(splitted[0], 64)
cm.idle, _ = strconv.ParseFloat(splitted[1], 64)
cm.other, _ = strconv.ParseFloat(splitted[2], 64)
cm.total, _ = strconv.ParseFloat(splitted[3], 64)
}
return &cm
}
// Execute the sinfo command and return its output
func CPUsData() []byte {
cmd := exec.Command("sinfo", "-h", "-o %C")
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
out, _ := ioutil.ReadAll(stdout)
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}
return out
}
/*
* Implement the Prometheus Collector interface and feed the
* Slurm scheduler metrics into it.
* https://godoc.org/github.com/prometheus/client_golang/prometheus#Collector
*/
func NewCPUsCollector() *CPUsCollector {
return &CPUsCollector{
alloc: prometheus.NewDesc("slurm_cpus_alloc", "Allocated CPUs", nil, nil),
idle: prometheus.NewDesc("slurm_cpus_idle", "Idle CPUs", nil, nil),
other: prometheus.NewDesc("slurm_cpus_other", "Mix CPUs", nil, nil),
total: prometheus.NewDesc("slurm_cpus_total", "Total CPUs", nil, nil),
}
}
type CPUsCollector struct {
alloc *prometheus.Desc
idle *prometheus.Desc
other *prometheus.Desc
total *prometheus.Desc
}
// Send all metric descriptions
func (cc *CPUsCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- cc.alloc
ch <- cc.idle
ch <- cc.other
ch <- cc.total
}
func (cc *CPUsCollector) Collect(ch chan<- prometheus.Metric) {
cm := CPUsGetMetrics()
ch <- prometheus.MustNewConstMetric(cc.alloc, prometheus.GaugeValue, cm.alloc)
ch <- prometheus.MustNewConstMetric(cc.idle, prometheus.GaugeValue, cm.idle)
ch <- prometheus.MustNewConstMetric(cc.other, prometheus.GaugeValue, cm.other)
ch <- prometheus.MustNewConstMetric(cc.total, prometheus.GaugeValue, cm.total)
}