| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | // Copyright 2016 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-03 04:35:24 -07:00
										 |  |  | //go:build !nodrbd
 | 
					
						
							| 
									
										
										
										
											2020-06-12 01:26:30 -07:00
										 |  |  | // +build !nodrbd
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bufio" | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Numerical metric provided by /proc/drbd.
 | 
					
						
							|  |  |  | type drbdNumericalMetric struct { | 
					
						
							|  |  |  | 	desc       *prometheus.Desc | 
					
						
							|  |  |  | 	valueType  prometheus.ValueType | 
					
						
							|  |  |  | 	multiplier float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | func newDRBDNumericalMetric(name, desc string, valueType prometheus.ValueType, multiplier float64) drbdNumericalMetric { | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	return drbdNumericalMetric{ | 
					
						
							|  |  |  | 		desc: prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 			prometheus.BuildFQName(namespace, "drbd", name), | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 			desc, | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 			[]string{"device"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 		valueType:  valueType, | 
					
						
							|  |  |  | 		multiplier: multiplier, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // String pair metric provided by /proc/drbd.
 | 
					
						
							|  |  |  | type drbdStringPairMetric struct { | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 	desc    *prometheus.Desc | 
					
						
							|  |  |  | 	valueOK string | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | func (m *drbdStringPairMetric) isOkay(v string) float64 { | 
					
						
							|  |  |  | 	if v == m.valueOK { | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 		return 1 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	return 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | func newDRBDStringPairMetric(name, desc, valueOK string) drbdStringPairMetric { | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	return drbdStringPairMetric{ | 
					
						
							|  |  |  | 		desc: prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 			prometheus.BuildFQName(namespace, "drbd", name), | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 			desc, | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 			[]string{"device", "node"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		valueOK: valueOK, | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | type drbdCollector struct { | 
					
						
							|  |  |  | 	numerical  map[string]drbdNumericalMetric | 
					
						
							|  |  |  | 	stringPair map[string]drbdStringPairMetric | 
					
						
							|  |  |  | 	connected  *prometheus.Desc | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger     *slog.Logger | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 	registerCollector("drbd", defaultDisabled, newDRBDCollector) | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func newDRBDCollector(logger *slog.Logger) (Collector, error) { | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 	return &drbdCollector{ | 
					
						
							|  |  |  | 		numerical: map[string]drbdNumericalMetric{ | 
					
						
							|  |  |  | 			"ns": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"network_sent_bytes_total", | 
					
						
							|  |  |  | 				"Total number of bytes sent via the network.", | 
					
						
							|  |  |  | 				prometheus.CounterValue, | 
					
						
							|  |  |  | 				1024, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"nr": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"network_received_bytes_total", | 
					
						
							|  |  |  | 				"Total number of bytes received via the network.", | 
					
						
							|  |  |  | 				prometheus.CounterValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"dw": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"disk_written_bytes_total", | 
					
						
							|  |  |  | 				"Net data written on local hard disk; in bytes.", | 
					
						
							|  |  |  | 				prometheus.CounterValue, | 
					
						
							|  |  |  | 				1024, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"dr": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"disk_read_bytes_total", | 
					
						
							|  |  |  | 				"Net data read from local hard disk; in bytes.", | 
					
						
							|  |  |  | 				prometheus.CounterValue, | 
					
						
							|  |  |  | 				1024, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"al": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"activitylog_writes_total", | 
					
						
							|  |  |  | 				"Number of updates of the activity log area of the meta data.", | 
					
						
							|  |  |  | 				prometheus.CounterValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"bm": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"bitmap_writes_total", | 
					
						
							|  |  |  | 				"Number of updates of the bitmap area of the meta data.", | 
					
						
							|  |  |  | 				prometheus.CounterValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"lo": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"local_pending", | 
					
						
							|  |  |  | 				"Number of open requests to the local I/O sub-system.", | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"pe": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"remote_pending", | 
					
						
							|  |  |  | 				"Number of requests sent to the peer, but that have not yet been answered by the latter.", | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"ua": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"remote_unacknowledged", | 
					
						
							|  |  |  | 				"Number of requests received by the peer via the network connection, but that have not yet been answered.", | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"ap": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"application_pending", | 
					
						
							|  |  |  | 				"Number of block I/O requests forwarded to DRBD, but not yet answered by DRBD.", | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"ep": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"epochs", | 
					
						
							|  |  |  | 				"Number of Epochs currently on the fly.", | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				1, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"oos": newDRBDNumericalMetric( | 
					
						
							|  |  |  | 				"out_of_sync_bytes", | 
					
						
							|  |  |  | 				"Amount of data known to be out of sync; in bytes.", | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				1024, | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		stringPair: map[string]drbdStringPairMetric{ | 
					
						
							|  |  |  | 			"ro": newDRBDStringPairMetric( | 
					
						
							|  |  |  | 				"node_role_is_primary", | 
					
						
							|  |  |  | 				"Whether the role of the node is in the primary state.", | 
					
						
							|  |  |  | 				"Primary", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"ds": newDRBDStringPairMetric( | 
					
						
							|  |  |  | 				"disk_state_is_up_to_date", | 
					
						
							|  |  |  | 				"Whether the disk of the node is up to date.", | 
					
						
							|  |  |  | 				"UpToDate", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		connected: prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName(namespace, "drbd", "connected"), | 
					
						
							|  |  |  | 			"Whether DRBD is connected to the peer.", | 
					
						
							|  |  |  | 			[]string{"device"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 		logger: logger, | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 10:47:20 -08:00
										 |  |  | func (c *drbdCollector) Update(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	statsFile := procFilePath("drbd") | 
					
						
							| 
									
										
										
										
											2016-12-16 02:45:14 -08:00
										 |  |  | 	file, err := os.Open(statsFile) | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 		if errors.Is(err, os.ErrNotExist) { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 			c.logger.Debug("stats file does not exist, skipping", "file", statsFile, "err", err) | 
					
						
							| 
									
										
										
										
											2020-02-19 07:11:29 -08:00
										 |  |  | 			return ErrNoData | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-16 02:45:14 -08:00
										 |  |  | 	defer file.Close() | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 02:45:14 -08:00
										 |  |  | 	scanner := bufio.NewScanner(file) | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	scanner.Split(bufio.ScanWords) | 
					
						
							|  |  |  | 	device := "unknown" | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	for scanner.Scan() { | 
					
						
							|  |  |  | 		field := scanner.Text() | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		kv := strings.Split(field, ":") | 
					
						
							|  |  |  | 		if len(kv) != 2 { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 			c.logger.Debug("skipping invalid key:value pair", "field", field) | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if id, err := strconv.ParseUint(kv[0], 10, 64); err == nil && kv[1] == "" { | 
					
						
							|  |  |  | 			// New DRBD device encountered.
 | 
					
						
							|  |  |  | 			device = fmt.Sprintf("drbd%d", id) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if m, ok := c.numerical[kv[0]]; ok { | 
					
						
							|  |  |  | 			// Numerical value.
 | 
					
						
							|  |  |  | 			v, err := strconv.ParseFloat(kv[1], 64) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				m.desc, | 
					
						
							|  |  |  | 				m.valueType, | 
					
						
							|  |  |  | 				v*m.multiplier, | 
					
						
							|  |  |  | 				device, | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if m, ok := c.stringPair[kv[0]]; ok { | 
					
						
							|  |  |  | 			// String pair value.
 | 
					
						
							|  |  |  | 			values := strings.Split(kv[1], "/") | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				m.desc, | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				m.isOkay(values[0]), | 
					
						
							|  |  |  | 				device, | 
					
						
							|  |  |  | 				"local", | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				m.desc, | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				m.isOkay(values[1]), | 
					
						
							|  |  |  | 				device, | 
					
						
							|  |  |  | 				"remote", | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if kv[0] == "cs" { | 
					
						
							|  |  |  | 			// Connection state.
 | 
					
						
							|  |  |  | 			var connected float64 | 
					
						
							|  |  |  | 			if kv[1] == "Connected" { | 
					
						
							|  |  |  | 				connected = 1 | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.connected, | 
					
						
							|  |  |  | 				prometheus.GaugeValue, | 
					
						
							|  |  |  | 				connected, | 
					
						
							|  |  |  | 				device, | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 		c.logger.Debug("unhandled key-value pair", "key", kv[0], "value", kv[1]) | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-04 07:40:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-16 02:36:36 -08:00
										 |  |  | 	return scanner.Err() | 
					
						
							| 
									
										
										
										
											2016-12-05 02:37:35 -08:00
										 |  |  | } |