@@ -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) {
7374type 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