mirror of
				https://github.com/prometheus/node_exporter.git
				synced 2025-08-20 18:33:52 -07:00 
			
		
		
		
	Generate descriptors in compile-time
Signed-off-by: Naoki MATSUMOTO <m.naoki9911@gmail.com>
This commit is contained in:
		
							parent
							
								
									96ad96ccbb
								
							
						
					
					
						commit
						5b28ee23f1
					
				| 
						 | 
					@ -26,11 +26,41 @@ import (
 | 
				
			||||||
	"github.com/prometheus/procfs/sysfs"
 | 
						"github.com/prometheus/procfs/sysfs"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						pcideviceSubsystem = "pcidevice"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						pcideviceLabelNames = []string{"segment", "bus", "device", "function"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pcideviceMaxLinkTSDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, pcideviceSubsystem, "max_link_transfers_per_second"),
 | 
				
			||||||
 | 
							"Value of maximum link's transfers per second (T/s)",
 | 
				
			||||||
 | 
							pcideviceLabelNames, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						pcideviceMaxLinkWidthDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, pcideviceSubsystem, "max_link_width"),
 | 
				
			||||||
 | 
							"Value of maximum link's width (number of lanes)",
 | 
				
			||||||
 | 
							pcideviceLabelNames, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pcideviceCurrentLinkTSDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, pcideviceSubsystem, "current_link_transfers_per_second"),
 | 
				
			||||||
 | 
							"Value of current link's transfers per second (T/s)",
 | 
				
			||||||
 | 
							pcideviceLabelNames, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						pcideviceCurrentLinkWidthDesc = prometheus.NewDesc(
 | 
				
			||||||
 | 
							prometheus.BuildFQName(namespace, pcideviceSubsystem, "current_link_width"),
 | 
				
			||||||
 | 
							"Value of current link's width (number of lanes)",
 | 
				
			||||||
 | 
							pcideviceLabelNames, nil,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type pciDeviceCollector struct {
 | 
					type pciDeviceCollector struct {
 | 
				
			||||||
	fs          sysfs.FS
 | 
						fs       sysfs.FS
 | 
				
			||||||
	metricDescs map[string]*prometheus.Desc
 | 
						infoDesc typedDesc
 | 
				
			||||||
	logger      *slog.Logger
 | 
						descs    []typedFactorDesc
 | 
				
			||||||
	subsystem   string
 | 
						logger   *slog.Logger
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
| 
						 | 
					@ -39,42 +69,34 @@ func init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewPciDeviceCollector returns a new Collector exposing PCI devices stats.
 | 
					// NewPciDeviceCollector returns a new Collector exposing PCI devices stats.
 | 
				
			||||||
func NewPciDeviceCollector(logger *slog.Logger) (Collector, error) {
 | 
					func NewPciDeviceCollector(logger *slog.Logger) (Collector, error) {
 | 
				
			||||||
	var i pciDeviceCollector
 | 
						fs, err := sysfs.NewFS(*sysPath)
 | 
				
			||||||
	var err error
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	i.fs, err = sysfs.NewFS(*sysPath)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("failed to open sysfs: %w", err)
 | 
							return nil, fmt.Errorf("failed to open sysfs: %w", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	i.logger = logger
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Detailed description for all metrics.
 | 
						c := pciDeviceCollector{
 | 
				
			||||||
	descriptions := map[string]string{
 | 
							fs:     fs,
 | 
				
			||||||
		"max_link_transfers_per_second":     "Value of maximum link's transfers per second (T/s)",
 | 
							logger: logger,
 | 
				
			||||||
		"max_link_width":                    "Value of maximum link's width (number of lanes)",
 | 
							infoDesc: typedDesc{
 | 
				
			||||||
		"current_link_transfers_per_second": "Value of current link's transfers per second (T/s)",
 | 
								desc: prometheus.NewDesc(
 | 
				
			||||||
		"current_link_width":                "Value of current link's width (number of lanes)",
 | 
									prometheus.BuildFQName(namespace, pcideviceSubsystem, "info"),
 | 
				
			||||||
 | 
									"Non-numeric data from /sys/bus/pci/devices/<location>, value is always 1.",
 | 
				
			||||||
 | 
									append(pcideviceLabelNames,
 | 
				
			||||||
 | 
										[]string{"parent_segment", "parent_bus", "parent_device", "parent_function",
 | 
				
			||||||
 | 
											"class_id", "vendor_id", "subsystem_vendor_id", "subsystem_device_id", "revision"}...),
 | 
				
			||||||
 | 
									nil,
 | 
				
			||||||
 | 
								),
 | 
				
			||||||
 | 
								valueType: prometheus.GaugeValue,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							descs: []typedFactorDesc{
 | 
				
			||||||
 | 
								{desc: pcideviceMaxLinkTSDesc, valueType: prometheus.GaugeValue},
 | 
				
			||||||
 | 
								{desc: pcideviceMaxLinkWidthDesc, valueType: prometheus.GaugeValue},
 | 
				
			||||||
 | 
								{desc: pcideviceCurrentLinkTSDesc, valueType: prometheus.GaugeValue},
 | 
				
			||||||
 | 
								{desc: pcideviceCurrentLinkWidthDesc, valueType: prometheus.GaugeValue},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	i.metricDescs = make(map[string]*prometheus.Desc)
 | 
						return &c, nil
 | 
				
			||||||
	i.subsystem = "pcidevice"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for metricName, description := range descriptions {
 | 
					 | 
				
			||||||
		i.metricDescs[metricName] = prometheus.NewDesc(
 | 
					 | 
				
			||||||
			prometheus.BuildFQName(namespace, i.subsystem, metricName),
 | 
					 | 
				
			||||||
			description,
 | 
					 | 
				
			||||||
			[]string{"segment", "bus", "device", "function"},
 | 
					 | 
				
			||||||
			nil,
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &i, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *pciDeviceCollector) pushMetric(ch chan<- prometheus.Metric, name string, value *float64, location sysfs.PciDeviceLocation, valueType prometheus.ValueType) {
 | 
					 | 
				
			||||||
	if value != nil {
 | 
					 | 
				
			||||||
		ch <- prometheus.MustNewConstMetric(c.metricDescs[name], valueType, *value, location.Strings()...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *pciDeviceCollector) Update(ch chan<- prometheus.Metric) error {
 | 
					func (c *pciDeviceCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
| 
						 | 
					@ -88,50 +110,33 @@ func (c *pciDeviceCollector) Update(ch chan<- prometheus.Metric) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, device := range devices {
 | 
						for _, device := range devices {
 | 
				
			||||||
		// The format follows the definition in drivers/pci/pci-sysfs.c
 | 
					 | 
				
			||||||
		infos := [][]string{
 | 
					 | 
				
			||||||
			{"class_id", fmt.Sprintf("0x%06x", device.Class)},
 | 
					 | 
				
			||||||
			{"vendor_id", fmt.Sprintf("0x%04x", device.Device)},
 | 
					 | 
				
			||||||
			{"subsystem_vendor_id", fmt.Sprintf("0x%04x", device.SubsystemVendor)},
 | 
					 | 
				
			||||||
			{"subsystem_device_id", fmt.Sprintf("0x%04x", device.SubsystemDevice)},
 | 
					 | 
				
			||||||
			{"revision", fmt.Sprintf("0x%02x", device.Revision)},
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		labels := []string{}
 | 
					 | 
				
			||||||
		values := []string{}
 | 
					 | 
				
			||||||
		for i := range infos {
 | 
					 | 
				
			||||||
			labels = append(labels, infos[i][0])
 | 
					 | 
				
			||||||
			values = append(values, infos[i][1])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// The device location is represented in separated format.
 | 
							// The device location is represented in separated format.
 | 
				
			||||||
		labels = append(labels, []string{"segment", "bus", "device", "function"}...)
 | 
							values := device.Location.Strings()
 | 
				
			||||||
		values = append(values, device.Location.Strings()...)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		labels = append(labels, []string{"parent_segment", "parent_bus", "parent_device", "parent_function"}...)
 | 
					 | 
				
			||||||
		if device.ParentLocation != nil {
 | 
							if device.ParentLocation != nil {
 | 
				
			||||||
			values = append(values, device.ParentLocation.Strings()...)
 | 
								values = append(values, device.ParentLocation.Strings()...)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			// TODO: is this ok?
 | 
					 | 
				
			||||||
			values = append(values, []string{"*", "*", "*", "*"}...)
 | 
								values = append(values, []string{"*", "*", "*", "*"}...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							values = append(values, fmt.Sprintf("0x%06x", device.Class))
 | 
				
			||||||
 | 
							values = append(values, fmt.Sprintf("0x%04x", device.Device))
 | 
				
			||||||
 | 
							values = append(values, fmt.Sprintf("0x%04x", device.SubsystemVendor))
 | 
				
			||||||
 | 
							values = append(values, fmt.Sprintf("0x%04x", device.SubsystemDevice))
 | 
				
			||||||
 | 
							values = append(values, fmt.Sprintf("0x%02x", device.Revision))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		infoDesc := prometheus.NewDesc(
 | 
							ch <- c.infoDesc.mustNewConstMetric(1.0, values...)
 | 
				
			||||||
			prometheus.BuildFQName(namespace, c.subsystem, "info"),
 | 
					 | 
				
			||||||
			"Non-numeric data from /sys/bus/pci/devices/<location>, value is always 1.",
 | 
					 | 
				
			||||||
			labels,
 | 
					 | 
				
			||||||
			nil,
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
		ch <- prometheus.MustNewConstMetric(infoDesc, prometheus.GaugeValue, 1.0, values...)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// MaxLinkSpeed and CurrentLinkSpeed are represnted in GT/s
 | 
							// MaxLinkSpeed and CurrentLinkSpeed are represnted in GT/s
 | 
				
			||||||
		maxLinkSpeedTS := float64(int64(*device.MaxLinkSpeed * 1e9))
 | 
							maxLinkSpeedTS := float64(int64(*device.MaxLinkSpeed * 1e9))
 | 
				
			||||||
		currentLinkSpeedTS := float64(int64(*device.CurrentLinkSpeed * 1e9))
 | 
							currentLinkSpeedTS := float64(int64(*device.CurrentLinkSpeed * 1e9))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		c.pushMetric(ch, "max_link_transfers_per_second", &maxLinkSpeedTS, device.Location, prometheus.GaugeValue)
 | 
							for i, val := range []float64{
 | 
				
			||||||
		c.pushMetric(ch, "max_link_width", device.MaxLinkWidth, device.Location, prometheus.GaugeValue)
 | 
								maxLinkSpeedTS,
 | 
				
			||||||
		c.pushMetric(ch, "current_link_transfers_per_second", ¤tLinkSpeedTS, device.Location, prometheus.GaugeValue)
 | 
								float64(*device.MaxLinkWidth),
 | 
				
			||||||
		c.pushMetric(ch, "current_link_width", device.CurrentLinkWidth, device.Location, prometheus.GaugeValue)
 | 
								currentLinkSpeedTS,
 | 
				
			||||||
 | 
								float64(*device.CurrentLinkWidth),
 | 
				
			||||||
 | 
							} {
 | 
				
			||||||
 | 
								ch <- c.descs[i].mustNewConstMetric(val, device.Location.Strings()...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue