| 
									
										
										
										
											2015-09-26 08:36:40 -07:00
										 |  |  | // Copyright 2015 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 !nomdadm
 | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | // +build !nomdadm
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 	"github.com/prometheus/procfs" | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | type mdadmCollector struct { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger *slog.Logger | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 	registerCollector("mdadm", defaultEnabled, NewMdadmCollector) | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 08:44:53 -08:00
										 |  |  | // NewMdadmCollector returns a new Collector exposing raid statistics.
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func NewMdadmCollector(logger *slog.Logger) (Collector, error) { | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 	return &mdadmCollector{logger}, nil | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 	activeDesc = prometheus.NewDesc( | 
					
						
							|  |  |  | 		prometheus.BuildFQName(namespace, "md", "state"), | 
					
						
							|  |  |  | 		"Indicates the state of md-device.", | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		[]string{"device"}, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 		prometheus.Labels{"state": "active"}, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 	inActiveDesc = prometheus.NewDesc( | 
					
						
							|  |  |  | 		prometheus.BuildFQName(namespace, "md", "state"), | 
					
						
							|  |  |  | 		"Indicates the state of md-device.", | 
					
						
							|  |  |  | 		[]string{"device"}, | 
					
						
							|  |  |  | 		prometheus.Labels{"state": "inactive"}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	recoveringDesc = prometheus.NewDesc( | 
					
						
							|  |  |  | 		prometheus.BuildFQName(namespace, "md", "state"), | 
					
						
							|  |  |  | 		"Indicates the state of md-device.", | 
					
						
							|  |  |  | 		[]string{"device"}, | 
					
						
							|  |  |  | 		prometheus.Labels{"state": "recovering"}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	resyncDesc = prometheus.NewDesc( | 
					
						
							|  |  |  | 		prometheus.BuildFQName(namespace, "md", "state"), | 
					
						
							|  |  |  | 		"Indicates the state of md-device.", | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		[]string{"device"}, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 		prometheus.Labels{"state": "resync"}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2020-09-27 04:44:45 -07:00
										 |  |  | 	checkDesc = prometheus.NewDesc( | 
					
						
							|  |  |  | 		prometheus.BuildFQName(namespace, "md", "state"), | 
					
						
							|  |  |  | 		"Indicates the state of md-device.", | 
					
						
							|  |  |  | 		[]string{"device"}, | 
					
						
							|  |  |  | 		prometheus.Labels{"state": "check"}, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	disksDesc = prometheus.NewDesc( | 
					
						
							|  |  |  | 		prometheus.BuildFQName(namespace, "md", "disks"), | 
					
						
							|  |  |  | 		"Number of active/failed/spare disks of device.", | 
					
						
							|  |  |  | 		[]string{"device", "state"}, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		nil, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	disksTotalDesc = prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 		prometheus.BuildFQName(namespace, "md", "disks_required"), | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		"Total number of disks of device.", | 
					
						
							|  |  |  | 		[]string{"device"}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blocksTotalDesc = prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 		prometheus.BuildFQName(namespace, "md", "blocks"), | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		"Total number of blocks on device.", | 
					
						
							|  |  |  | 		[]string{"device"}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	blocksSyncedDesc = prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2017-09-28 06:06:26 -07:00
										 |  |  | 		prometheus.BuildFQName(namespace, "md", "blocks_synced"), | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		"Number of blocks synced on device.", | 
					
						
							|  |  |  | 		[]string{"device"}, | 
					
						
							|  |  |  | 		nil, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-28 10:47:20 -08:00
										 |  |  | func (c *mdadmCollector) Update(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 	fs, err := procfs.NewFS(*procPath) | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("failed to open procfs: %w", err) | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mdStats, err := fs.MDStat() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 06:11:19 -07: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("Not collecting mdstat, file does not exist", "file", *procPath) | 
					
						
							| 
									
										
										
										
											2020-02-19 07:11:29 -08:00
										 |  |  | 			return ErrNoData | 
					
						
							| 
									
										
										
										
											2017-02-28 10:47:20 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-15 13:27:14 -07:00
										 |  |  | 		return fmt.Errorf("error parsing mdstatus: %w", err) | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 	for _, mdStat := range mdStats { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 		c.logger.Debug("collecting metrics for device", "device", mdStat.Name) | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		stateVals := make(map[string]float64) | 
					
						
							|  |  |  | 		stateVals[mdStat.ActivityState] = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			disksTotalDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			float64(mdStat.DisksTotal), | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 		) | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			disksDesc, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 			prometheus.GaugeValue, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			float64(mdStat.DisksActive), | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 			"active", | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		) | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			disksDesc, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 			prometheus.GaugeValue, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			float64(mdStat.DisksFailed), | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 			"failed", | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		) | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			disksDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			float64(mdStat.DisksSpare), | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 			"spare", | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			activeDesc, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 			prometheus.GaugeValue, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			stateVals["active"], | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		) | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			inActiveDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			stateVals["inactive"], | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			recoveringDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			stateVals["recovering"], | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			resyncDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			stateVals["resyncing"], | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 04:44:45 -07:00
										 |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			checkDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			stateVals["checking"], | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			blocksTotalDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			float64(mdStat.BlocksTotal), | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		) | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			blocksSyncedDesc, | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							| 
									
										
										
										
											2019-07-01 02:56:06 -07:00
										 |  |  | 			float64(mdStat.BlocksSynced), | 
					
						
							|  |  |  | 			mdStat.Name, | 
					
						
							| 
									
										
										
										
											2015-09-07 06:49:30 -07:00
										 |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |