aboutsummaryrefslogtreecommitdiff
path: root/collector/drbd_linux.go
diff options
context:
space:
mode:
authorEd Schouten <ed@kumina.nl>2016-12-05 11:37:35 +0100
committerEd Schouten <ed@kumina.nl>2016-12-11 11:55:28 +0100
commit6269f7502a80558da5c6ea2f40ef0c0261664321 (patch)
tree434e6f0b18df0a3f0106effcc337cdb8584cc26a /collector/drbd_linux.go
parentff5b9010653bab4d4459a693ac7357e30e83f0b0 (diff)
downloadprometheus_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.go211
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
14package collector
15
16import (
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.
28type drbdNumericalMetric struct {
29 desc *prometheus.Desc
30 valueType prometheus.ValueType
31 multiplier float64
32}
33
34func 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.
46type drbdStringPairMetric struct {
47 desc *prometheus.Desc
48 valueOkay string
49}
50
51func (metric *drbdStringPairMetric) isOkay(value string) float64 {
52 if value == metric.valueOkay {
53 return 1
54 }
55 return 0
56}
57
58func 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
68var (
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
148type drbdCollector struct{}
149
150func init() {
151 Factories["drbd"] = NewDrbdCollector
152}
153
154func NewDrbdCollector() (Collector, error) {
155 return &drbdCollector{}, nil
156}
157
158func (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}