Skip to content

Commit 9aae303

Browse files
authored
Merge pull request prometheus#2289 from tanguyfalconnet/ethtool-lock
ethtool_linux: add mutex around entries access
2 parents 086fdfe + 5c8407b commit 9aae303

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

collector/ethtool_linux.go

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"regexp"
2828
"sort"
2929
"strings"
30+
"sync"
3031
"syscall"
3132

3233
"github.com/go-kit/log"
@@ -73,6 +74,7 @@ func (e *ethtoolLibrary) LinkInfo(intf string) (ethtool.EthtoolCmd, error) {
7374
type ethtoolCollector struct {
7475
fs sysfs.FS
7576
entries map[string]*prometheus.Desc
77+
entriesMutex sync.Mutex
7678
ethtool Ethtool
7779
deviceFilter netDevFilter
7880
infoDesc *prometheus.Desc
@@ -233,9 +235,9 @@ func (c *ethtoolCollector) updatePortCapabilities(ch chan<- prometheus.Metric, p
233235
if linkModes&(1<<unix.ETHTOOL_LINK_MODE_Asym_Pause_BIT) != 0 {
234236
asymmetricPause = 1.0
235237
}
236-
ch <- prometheus.MustNewConstMetric(c.entries[fmt.Sprintf("%s_autonegotiate", prefix)], prometheus.GaugeValue, autonegotiate, device)
237-
ch <- prometheus.MustNewConstMetric(c.entries[fmt.Sprintf("%s_pause", prefix)], prometheus.GaugeValue, pause, device)
238-
ch <- prometheus.MustNewConstMetric(c.entries[fmt.Sprintf("%s_asymmetricpause", prefix)], prometheus.GaugeValue, asymmetricPause, device)
238+
ch <- prometheus.MustNewConstMetric(c.entry(fmt.Sprintf("%s_autonegotiate", prefix)), prometheus.GaugeValue, autonegotiate, device)
239+
ch <- prometheus.MustNewConstMetric(c.entry(fmt.Sprintf("%s_pause", prefix)), prometheus.GaugeValue, pause, device)
240+
ch <- prometheus.MustNewConstMetric(c.entry(fmt.Sprintf("%s_asymmetricpause", prefix)), prometheus.GaugeValue, asymmetricPause, device)
239241
}
240242

241243
// updatePortInfo generates port type metrics to indicate if the network devices supports Twisted Pair, optical fiber, etc.
@@ -251,7 +253,7 @@ func (c *ethtoolCollector) updatePortInfo(ch chan<- prometheus.Metric, device st
251253
"Backplane": unix.ETHTOOL_LINK_MODE_Backplane_BIT,
252254
} {
253255
if linkModes&(1<<bit) != 0 {
254-
ch <- prometheus.MustNewConstMetric(c.entries["supported_port"], prometheus.GaugeValue, 1.0, device, name)
256+
ch <- prometheus.MustNewConstMetric(c.entry("supported_port"), prometheus.GaugeValue, 1.0, device, name)
255257
}
256258

257259
}
@@ -299,7 +301,7 @@ func (c *ethtoolCollector) updateSpeeds(ch chan<- prometheus.Metric, prefix stri
299301
unix.ETHTOOL_LINK_MODE_25000baseCR_Full_BIT: {25000, full, "CR"},
300302
} {
301303
if linkModes&(1<<bit) != 0 {
302-
ch <- prometheus.MustNewConstMetric(c.entries[linkMode], prometheus.GaugeValue,
304+
ch <- prometheus.MustNewConstMetric(c.entry(linkMode), prometheus.GaugeValue,
303305
float64(labels.speed)*Mbps, device, labels.duplex, fmt.Sprintf("%dbase%s", labels.speed, labels.phy))
304306
}
305307
}
@@ -334,7 +336,7 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
334336
c.updatePortCapabilities(ch, "supported", device, linkInfo.Supported)
335337
c.updateSpeeds(ch, "advertised", device, linkInfo.Advertising)
336338
c.updatePortCapabilities(ch, "advertised", device, linkInfo.Advertising)
337-
ch <- prometheus.MustNewConstMetric(c.entries["autonegotiate"], prometheus.GaugeValue, float64(linkInfo.Autoneg), device)
339+
ch <- prometheus.MustNewConstMetric(c.entry("autonegotiate"), prometheus.GaugeValue, float64(linkInfo.Autoneg), device)
338340
} else {
339341
if errno, ok := err.(syscall.Errno); ok {
340342
if err == unix.EOPNOTSUPP {
@@ -420,19 +422,32 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
420422
val := stats[metric]
421423

422424
// Check to see if this metric exists; if not then create it and store it in c.entries.
423-
entry, exists := c.entries[metric]
424-
if !exists {
425-
entry = prometheus.NewDesc(
426-
metricFQName,
427-
fmt.Sprintf("Network interface %s", metric),
428-
[]string{"device"}, nil,
429-
)
430-
c.entries[metric] = entry
431-
}
425+
entry := c.entryWithCreate(metric, metricFQName)
432426
ch <- prometheus.MustNewConstMetric(
433427
entry, prometheus.UntypedValue, float64(val), device)
434428
}
435429
}
436430

437431
return nil
438432
}
433+
434+
func (c *ethtoolCollector) entryWithCreate(key, metricFQName string) *prometheus.Desc {
435+
c.entriesMutex.Lock()
436+
defer c.entriesMutex.Unlock()
437+
438+
if _, ok := c.entries[key]; !ok {
439+
c.entries[key] = prometheus.NewDesc(
440+
metricFQName,
441+
fmt.Sprintf("Network interface %s", key),
442+
[]string{"device"}, nil,
443+
)
444+
}
445+
446+
return c.entries[key]
447+
}
448+
449+
func (c *ethtoolCollector) entry(key string) *prometheus.Desc {
450+
c.entriesMutex.Lock()
451+
defer c.entriesMutex.Unlock()
452+
return c.entries[key]
453+
}

0 commit comments

Comments
 (0)