|
|
|
|
@ -49,6 +49,7 @@ type Ethtool interface { |
|
|
|
|
DriverInfo(string) (ethtool.DrvInfo, error) |
|
|
|
|
Stats(string) (map[string]uint64, error) |
|
|
|
|
LinkInfo(string) (ethtool.EthtoolCmd, error) |
|
|
|
|
GetChannels(string) (ethtool.Channels, error) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type ethtoolLibrary struct { |
|
|
|
|
@ -69,6 +70,10 @@ func (e *ethtoolLibrary) LinkInfo(intf string) (ethtool.EthtoolCmd, error) { |
|
|
|
|
return ethtoolCmd, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (e *ethtoolLibrary) GetChannels(intf string) (ethtool.Channels, error) { |
|
|
|
|
return e.ethtool.GetChannels(intf) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type ethtoolCollector struct { |
|
|
|
|
fs sysfs.FS |
|
|
|
|
entries map[string]*prometheus.Desc |
|
|
|
|
@ -199,6 +204,21 @@ func makeEthtoolCollector(logger *slog.Logger) (*ethtoolCollector, error) { |
|
|
|
|
"If this port is using autonegotiate", |
|
|
|
|
[]string{"device"}, nil, |
|
|
|
|
), |
|
|
|
|
|
|
|
|
|
// channel info
|
|
|
|
|
//
|
|
|
|
|
// Each metric will have four instances differentiated by its type,
|
|
|
|
|
// with type being one of rx, tx, other, or combined.
|
|
|
|
|
"channels_max": prometheus.NewDesc( |
|
|
|
|
prometheus.BuildFQName(namespace, "ethtool", "channels_max"), |
|
|
|
|
"Maximum supported network interface channels", |
|
|
|
|
[]string{"device", "type"}, nil, |
|
|
|
|
), |
|
|
|
|
"channels_current": prometheus.NewDesc( |
|
|
|
|
prometheus.BuildFQName(namespace, "ethtool", "channels_current"), |
|
|
|
|
"Currently configured network interface channels", |
|
|
|
|
[]string{"device", "type"}, nil, |
|
|
|
|
), |
|
|
|
|
}, |
|
|
|
|
infoDesc: prometheus.NewDesc( |
|
|
|
|
prometheus.BuildFQName(namespace, "ethtool", "info"), |
|
|
|
|
@ -370,6 +390,33 @@ func (c *ethtoolCollector) updateSpeeds(ch chan<- prometheus.Metric, prefix stri |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *ethtoolCollector) updateChannels(ch chan<- prometheus.Metric, device string) { |
|
|
|
|
channels, err := c.ethtool.GetChannels(device) |
|
|
|
|
if err != nil { |
|
|
|
|
if errno, ok := err.(syscall.Errno); ok { |
|
|
|
|
if err == unix.EOPNOTSUPP { |
|
|
|
|
c.logger.Debug("ethtool driver info error", "err", err, "device", device, "errno", uint(errno)) |
|
|
|
|
} else if errno != 0 { |
|
|
|
|
c.logger.Error("ethtool get channels error", "err", err, "device", device, "errno", uint(errno)) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
c.logger.Error("ethtool get channels error", "err", err, "device", device) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_max"), prometheus.GaugeValue, float64(channels.MaxRx), device, "rx") |
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_max"), prometheus.GaugeValue, float64(channels.MaxTx), device, "tx") |
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_max"), prometheus.GaugeValue, float64(channels.MaxOther), device, "other") |
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_max"), prometheus.GaugeValue, float64(channels.MaxCombined), device, "combined") |
|
|
|
|
|
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_current"), prometheus.GaugeValue, float64(channels.RxCount), device, "rx") |
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_current"), prometheus.GaugeValue, float64(channels.TxCount), device, "tx") |
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_current"), prometheus.GaugeValue, float64(channels.OtherCount), device, "other") |
|
|
|
|
ch <- prometheus.MustNewConstMetric(c.entry("channels_current"), prometheus.GaugeValue, float64(channels.CombinedCount), device, "combined") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error { |
|
|
|
|
netClass, err := c.fs.NetClassDevices() |
|
|
|
|
if err != nil { |
|
|
|
|
@ -429,6 +476,8 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
c.updateChannels(ch, device) |
|
|
|
|
|
|
|
|
|
stats, err = c.ethtool.Stats(device) |
|
|
|
|
|
|
|
|
|
// If Stats() returns EOPNOTSUPP it doesn't support ethtool stats. Log that only at Debug level.
|
|
|
|
|
|