mirror of
				https://github.com/prometheus/node_exporter.git
				synced 2025-08-20 18:33:52 -07:00 
			
		
		
		
	Merge e001207733 into be19d537cd
				
					
				
			This commit is contained in:
		
						commit
						415ffc054b
					
				
							
								
								
									
										215
									
								
								collector/sas_linux.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								collector/sas_linux.go
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,215 @@
 | 
				
			||||||
 | 
					// 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//go:build !nocpu
 | 
				
			||||||
 | 
					// +build !nocpu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package collector
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Exported metrics, from /sys/class/sas_phy/<name>/*:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// - invalid_dword_count
 | 
				
			||||||
 | 
					// - loss_of_dword_sync_count
 | 
				
			||||||
 | 
					// - negotiated_linkrate
 | 
				
			||||||
 | 
					// - phy_reset_problem_count
 | 
				
			||||||
 | 
					// - running_disparity_error_count
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Four of these are counters, one is a gauge.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-kit/log"
 | 
				
			||||||
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
 | 
						"github.com/prometheus/procfs/sysfs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type sasCollector struct {
 | 
				
			||||||
 | 
						fs sysfs.FS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sasInvalidDword          *prometheus.Desc
 | 
				
			||||||
 | 
						sasLossOfDwordSync       *prometheus.Desc
 | 
				
			||||||
 | 
						sasNegotiatedLinkrate    *prometheus.Desc
 | 
				
			||||||
 | 
						sasPhyResetProblem       *prometheus.Desc
 | 
				
			||||||
 | 
						sasRunningDisparityError *prometheus.Desc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger log.Logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const sasCollectorSubsystem = "sas"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						registerCollector("sas", defaultEnabled, NewSASCollector)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewSASCollector returns a new Collector exposing SAS storage statistics.
 | 
				
			||||||
 | 
					func NewSASCollector(logger log.Logger) (Collector, error) {
 | 
				
			||||||
 | 
						fs, err := sysfs.NewFS(*sysPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("failed to open procfs: %w", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c := &sasCollector{
 | 
				
			||||||
 | 
							fs: fs,
 | 
				
			||||||
 | 
							sasInvalidDword: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, sasCollectorSubsystem, "phy_invalid_dword"),
 | 
				
			||||||
 | 
								"SAS PHY count of invalid dwords.",
 | 
				
			||||||
 | 
								[]string{"phy", "port", "host", "expander", "block_device", "sas_address"}, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							sasLossOfDwordSync: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, sasCollectorSubsystem, "phy_loss_of_dword_sync"),
 | 
				
			||||||
 | 
								"SAS PHY count of lost dword sync.",
 | 
				
			||||||
 | 
								[]string{"phy", "port", "host", "expander", "block_device", "sas_address"}, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							sasNegotiatedLinkrate: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, sasCollectorSubsystem, "phy_negotiated_linkrate"),
 | 
				
			||||||
 | 
								"SAS PHY negotiated link rate in Gbps.",
 | 
				
			||||||
 | 
								[]string{"phy", "port", "host", "expander", "block_device", "sas_address"}, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							sasPhyResetProblem: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, sasCollectorSubsystem, "phy_reset_problem"),
 | 
				
			||||||
 | 
								"SAS PHY count of reset problems.",
 | 
				
			||||||
 | 
								[]string{"phy", "port", "host", "expander", "block_device", "sas_address"}, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							sasRunningDisparityError: prometheus.NewDesc(
 | 
				
			||||||
 | 
								prometheus.BuildFQName(namespace, sasCollectorSubsystem, "phy_running_disparity_error"),
 | 
				
			||||||
 | 
								"SAS PHY count of running disparity errors.",
 | 
				
			||||||
 | 
								[]string{"phy", "port", "host", "expander", "block_device", "sas_address"}, nil,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
 | 
							logger: logger,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Update implements Collector and exposes cpu related metrics from /proc/stat and /sys/.../cpu/.
 | 
				
			||||||
 | 
					func (s *sasCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
 | 
						sasEndDevices, err := s.fs.SASEndDeviceClass()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sasExpanders, err := s.fs.SASExpanderClass()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sasHosts, err := s.fs.SASHostClass()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sasPhys, err := s.fs.SASPhyClass()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sasPorts, err := s.fs.SASPortClass()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, phy := range sasPhys {
 | 
				
			||||||
 | 
							// One per SAS link in the system.
 | 
				
			||||||
 | 
							phyName := phy.Name
 | 
				
			||||||
 | 
							portName := phy.SASPort
 | 
				
			||||||
 | 
							sasAddress := phy.SASAddress
 | 
				
			||||||
 | 
							hostName := ""
 | 
				
			||||||
 | 
							expanderName := ""
 | 
				
			||||||
 | 
							blockDeviceName := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Check to see if this Phy is connected directly to a SAS host (~controller card)
 | 
				
			||||||
 | 
							host := sasHosts.GetByPhy(phyName)
 | 
				
			||||||
 | 
							if host != nil {
 | 
				
			||||||
 | 
								hostName = host.Name
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							expander := sasExpanders.GetByPhy(phyName)
 | 
				
			||||||
 | 
							if expander != nil {
 | 
				
			||||||
 | 
								expanderName = expander.Name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// If we didn't find a host name before, then maybe it's connected
 | 
				
			||||||
 | 
								// host -> expander -> Phy.  So try checking the expander's Ports?
 | 
				
			||||||
 | 
								// TODO: Do this recursively for nested expanders.
 | 
				
			||||||
 | 
								if hostName == "" {
 | 
				
			||||||
 | 
									port := sasPorts.GetByExpander(expanderName)
 | 
				
			||||||
 | 
									if port != nil {
 | 
				
			||||||
 | 
										host := sasHosts.GetByPort(port.Name)
 | 
				
			||||||
 | 
										if host != nil {
 | 
				
			||||||
 | 
											hostName = host.Name
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// This is the best mapping that I've found for phy->blockDevice.  Yes, it's horrible.
 | 
				
			||||||
 | 
							port := sasPorts.GetByName(portName)
 | 
				
			||||||
 | 
							if port != nil {
 | 
				
			||||||
 | 
								for _, portEndDevice := range port.EndDevices {
 | 
				
			||||||
 | 
									endDevice := sasEndDevices.GetByName(portEndDevice)
 | 
				
			||||||
 | 
									if endDevice != nil {
 | 
				
			||||||
 | 
										if len(endDevice.BlockDevices) > 0 {
 | 
				
			||||||
 | 
											blockDeviceName = endDevice.BlockDevices[0]
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(s.sasInvalidDword,
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
								float64(phy.InvalidDwordCount),
 | 
				
			||||||
 | 
								phyName,
 | 
				
			||||||
 | 
								portName,
 | 
				
			||||||
 | 
								hostName,
 | 
				
			||||||
 | 
								expanderName,
 | 
				
			||||||
 | 
								blockDeviceName,
 | 
				
			||||||
 | 
								sasAddress)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(s.sasLossOfDwordSync,
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
								float64(phy.LossOfDwordSyncCount),
 | 
				
			||||||
 | 
								phyName,
 | 
				
			||||||
 | 
								portName,
 | 
				
			||||||
 | 
								hostName,
 | 
				
			||||||
 | 
								expanderName,
 | 
				
			||||||
 | 
								blockDeviceName,
 | 
				
			||||||
 | 
								sasAddress)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(s.sasNegotiatedLinkrate,
 | 
				
			||||||
 | 
								prometheus.GaugeValue,
 | 
				
			||||||
 | 
								float64(phy.NegotiatedLinkrate),
 | 
				
			||||||
 | 
								phyName,
 | 
				
			||||||
 | 
								portName,
 | 
				
			||||||
 | 
								hostName,
 | 
				
			||||||
 | 
								expanderName,
 | 
				
			||||||
 | 
								blockDeviceName,
 | 
				
			||||||
 | 
								sasAddress)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(s.sasPhyResetProblem,
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
								float64(phy.PhyResetProblemCount),
 | 
				
			||||||
 | 
								phyName,
 | 
				
			||||||
 | 
								portName,
 | 
				
			||||||
 | 
								hostName,
 | 
				
			||||||
 | 
								expanderName,
 | 
				
			||||||
 | 
								blockDeviceName,
 | 
				
			||||||
 | 
								sasAddress)
 | 
				
			||||||
 | 
							ch <- prometheus.MustNewConstMetric(s.sasRunningDisparityError,
 | 
				
			||||||
 | 
								prometheus.CounterValue,
 | 
				
			||||||
 | 
								float64(phy.RunningDisparityErrorCount),
 | 
				
			||||||
 | 
								phyName,
 | 
				
			||||||
 | 
								portName,
 | 
				
			||||||
 | 
								hostName,
 | 
				
			||||||
 | 
								expanderName,
 | 
				
			||||||
 | 
								blockDeviceName,
 | 
				
			||||||
 | 
								sasAddress)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in a new issue