diff options
author | Ed Schouten <ed@kumina.nl> | 2016-12-05 11:37:35 +0100 |
---|---|---|
committer | Ed Schouten <ed@kumina.nl> | 2016-12-11 11:55:28 +0100 |
commit | 6269f7502a80558da5c6ea2f40ef0c0261664321 (patch) | |
tree | 434e6f0b18df0a3f0106effcc337cdb8584cc26a /collector/drbd_linux.go | |
parent | ff5b9010653bab4d4459a693ac7357e30e83f0b0 (diff) | |
download | prometheus_node_collector-6269f7502a80558da5c6ea2f40ef0c0261664321.tar.bz2 prometheus_node_collector-6269f7502a80558da5c6ea2f40ef0c0261664321.tar.xz prometheus_node_collector-6269f7502a80558da5c6ea2f40ef0c0261664321.zip |
Add a collector for DRBD.
This collector exposes most of the useful information that can be found
in /proc/drbd. Sizes are normalised to be in bytes, as /proc/drbd uses
kibibytes.
Diffstat (limited to 'collector/drbd_linux.go')
-rw-r--r-- | collector/drbd_linux.go | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/collector/drbd_linux.go b/collector/drbd_linux.go new file mode 100644 index 0000000..37cbe9c --- /dev/null +++ b/collector/drbd_linux.go | |||
@@ -0,0 +1,211 @@ | |||
1 | // Copyright 2016 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | package collector | ||
15 | |||
16 | import ( | ||
17 | "bufio" | ||
18 | "fmt" | ||
19 | "os" | ||
20 | "strconv" | ||
21 | "strings" | ||
22 | |||
23 | "github.com/prometheus/client_golang/prometheus" | ||
24 | "github.com/prometheus/common/log" | ||
25 | ) | ||
26 | |||
27 | // Numerical metric provided by /proc/drbd. | ||
28 | type drbdNumericalMetric struct { | ||
29 | desc *prometheus.Desc | ||
30 | valueType prometheus.ValueType | ||
31 | multiplier float64 | ||
32 | } | ||
33 | |||
34 | func newDrbdNumericalMetric(name string, desc string, valueType prometheus.ValueType, multiplier float64) drbdNumericalMetric { | ||
35 | return drbdNumericalMetric{ | ||
36 | desc: prometheus.NewDesc( | ||
37 | prometheus.BuildFQName(Namespace, "drbd", name), | ||
38 | desc, | ||
39 | []string{"device"}, nil), | ||
40 | valueType: valueType, | ||
41 | multiplier: multiplier, | ||
42 | } | ||
43 | } | ||
44 | |||
45 | // String pair metric provided by /proc/drbd. | ||
46 | type drbdStringPairMetric struct { | ||
47 | desc *prometheus.Desc | ||
48 | valueOkay string | ||
49 | } | ||
50 | |||
51 | func (metric *drbdStringPairMetric) isOkay(value string) float64 { | ||
52 | if value == metric.valueOkay { | ||
53 | return 1 | ||
54 | } | ||
55 | return 0 | ||
56 | } | ||
57 | |||
58 | func newDrbdStringPairMetric(name string, desc string, valueOkay string) drbdStringPairMetric { | ||
59 | return drbdStringPairMetric{ | ||
60 | desc: prometheus.NewDesc( | ||
61 | prometheus.BuildFQName(Namespace, "drbd", name), | ||
62 | desc, | ||
63 | []string{"device", "node"}, nil), | ||
64 | valueOkay: valueOkay, | ||
65 | } | ||
66 | } | ||
67 | |||
68 | var ( | ||
69 | drbdNumericalMetrics = map[string]drbdNumericalMetric{ | ||
70 | "ns": newDrbdNumericalMetric( | ||
71 | "network_sent_bytes", | ||
72 | "Volume of net data sent to the partner via the network connection.", | ||
73 | prometheus.CounterValue, | ||
74 | 1024), | ||
75 | "nr": newDrbdNumericalMetric( | ||
76 | "network_received_bytes", | ||
77 | "Volume of net data received by the partner via the network connection.", | ||
78 | prometheus.CounterValue, | ||
79 | 1), | ||
80 | "dw": newDrbdNumericalMetric( | ||
81 | "disk_written_bytes", | ||
82 | "Net data written on local hard disk.", | ||
83 | prometheus.CounterValue, | ||
84 | 1024), | ||
85 | "dr": newDrbdNumericalMetric( | ||
86 | "disk_read_bytes", | ||
87 | "Net data read from local hard disk.", | ||
88 | prometheus.CounterValue, | ||
89 | 1024), | ||
90 | "al": newDrbdNumericalMetric( | ||
91 | "activitylog_writes", | ||
92 | "Number of updates of the activity log area of the meta data.", | ||
93 | prometheus.CounterValue, | ||
94 | 1), | ||
95 | "bm": newDrbdNumericalMetric( | ||
96 | "bitmap_writes", | ||
97 | "Number of updates of the bitmap area of the meta data.", | ||
98 | prometheus.CounterValue, | ||
99 | 1), | ||
100 | "lo": newDrbdNumericalMetric( | ||
101 | "local_pending", | ||
102 | "Number of open requests to the local I/O sub-system.", | ||
103 | prometheus.GaugeValue, | ||
104 | 1), | ||
105 | "pe": newDrbdNumericalMetric( | ||
106 | "remote_pending", | ||
107 | "Number of requests sent to the partner, but that have not yet been answered by the latter.", | ||
108 | prometheus.GaugeValue, | ||
109 | 1), | ||
110 | "ua": newDrbdNumericalMetric( | ||
111 | "remote_unacknowledged", | ||
112 | "Number of requests received by the partner via the network connection, but that have not yet been answered.", | ||
113 | prometheus.GaugeValue, | ||
114 | 1), | ||
115 | "ap": newDrbdNumericalMetric( | ||
116 | "application_pending", | ||
117 | "Number of block I/O requests forwarded to DRBD, but not yet answered by DRBD.", | ||
118 | prometheus.GaugeValue, | ||
119 | 1), | ||
120 | "ep": newDrbdNumericalMetric( | ||
121 | "epochs", | ||
122 | "Number of Epochs currently on the fly.", | ||
123 | prometheus.GaugeValue, | ||
124 | 1), | ||
125 | "oos": newDrbdNumericalMetric( | ||
126 | "out_of_sync_bytes", | ||
127 | "Amount of data known to be out of sync.", | ||
128 | prometheus.GaugeValue, | ||
129 | 1024), | ||
130 | } | ||
131 | drbdStringPairMetrics = map[string]drbdStringPairMetric{ | ||
132 | "ro": newDrbdStringPairMetric( | ||
133 | "node_role_is_primary", | ||
134 | "Whether the role of the node is in the primary state.", | ||
135 | "Primary"), | ||
136 | "ds": newDrbdStringPairMetric( | ||
137 | "disk_state_is_up_to_date", | ||
138 | "Whether the disk of the node is up to date.", | ||
139 | "UpToDate"), | ||
140 | } | ||
141 | |||
142 | drbdConnected = prometheus.NewDesc( | ||
143 | prometheus.BuildFQName(Namespace, "drbd", "connected"), | ||
144 | "Whether DRBD is connected to the partner.", | ||
145 | []string{"device"}, nil) | ||
146 | ) | ||
147 | |||
148 | type drbdCollector struct{} | ||
149 | |||
150 | func init() { | ||
151 | Factories["drbd"] = NewDrbdCollector | ||
152 | } | ||
153 | |||
154 | func NewDrbdCollector() (Collector, error) { | ||
155 | return &drbdCollector{}, nil | ||
156 | } | ||
157 | |||
158 | func (c *drbdCollector) Update(ch chan<- prometheus.Metric) (err error) { | ||
159 | statsFile := procFilePath("drbd") | ||
160 | f, err := os.Open(statsFile) | ||
161 | if err != nil { | ||
162 | if os.IsNotExist(err) { | ||
163 | log.Debugf("Not collecting DRBD statistics, as %s does not exist: %s", statsFile) | ||
164 | return nil | ||
165 | } | ||
166 | return err | ||
167 | } | ||
168 | defer f.Close() | ||
169 | |||
170 | scanner := bufio.NewScanner(f) | ||
171 | scanner.Split(bufio.ScanWords) | ||
172 | device := "unknown" | ||
173 | for scanner.Scan() { | ||
174 | field := scanner.Text() | ||
175 | if kv := strings.Split(field, ":"); len(kv) == 2 { | ||
176 | if id, err := strconv.ParseUint(kv[0], 10, 64); err == nil && kv[1] == "" { | ||
177 | device = fmt.Sprintf("drbd%d", id) | ||
178 | } else if metric, ok := drbdNumericalMetrics[kv[0]]; ok { | ||
179 | // Numerical value. | ||
180 | value, _ := strconv.ParseFloat(kv[1], 64) | ||
181 | ch <- prometheus.MustNewConstMetric( | ||
182 | metric.desc, metric.valueType, | ||
183 | value*metric.multiplier, device) | ||
184 | } else if metric, ok := drbdStringPairMetrics[kv[0]]; ok { | ||
185 | // String pair value. | ||
186 | values := strings.Split(kv[1], "/") | ||
187 | ch <- prometheus.MustNewConstMetric( | ||
188 | metric.desc, prometheus.GaugeValue, | ||
189 | metric.isOkay(values[0]), device, "local") | ||
190 | ch <- prometheus.MustNewConstMetric( | ||
191 | metric.desc, prometheus.GaugeValue, | ||
192 | metric.isOkay(values[1]), device, "remote") | ||
193 | } else if kv[0] == "cs" { | ||
194 | // Connection state. | ||
195 | var connected float64 = 0 | ||
196 | if kv[1] == "Connected" { | ||
197 | connected = 1 | ||
198 | } | ||
199 | ch <- prometheus.MustNewConstMetric( | ||
200 | drbdConnected, prometheus.GaugeValue, | ||
201 | connected, device) | ||
202 | |||
203 | } else { | ||
204 | log.Infof("Don't know how to process key-value pair [%s: %s]", kv[0], kv[1]) | ||
205 | } | ||
206 | } else { | ||
207 | log.Infof("Don't know how to process string %s", field) | ||
208 | } | ||
209 | } | ||
210 | return nil | ||
211 | } | ||