Skip to content

Commit cb7b5a7

Browse files
committed
netdev_common: Add mutex around metricDescs access
In certain instances on heavily loaded nodes with many network devices, there may be concurrent access to the netdev collector's `metricDescs` map, resulting in a panic. This adds a mutex to prevent concurrent reads and writes to the map. Signed-off-by: Brad Ison <[email protected]>
1 parent 996563f commit cb7b5a7

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

collector/netdev_common.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"net"
2424
"strconv"
25+
"sync"
2526

2627
"github.com/go-kit/log"
2728
"github.com/go-kit/log/level"
@@ -38,10 +39,11 @@ var (
3839
)
3940

4041
type netDevCollector struct {
41-
subsystem string
42-
deviceFilter netDevFilter
43-
metricDescs map[string]*prometheus.Desc
44-
logger log.Logger
42+
subsystem string
43+
deviceFilter netDevFilter
44+
metricDescsMutex sync.Mutex
45+
metricDescs map[string]*prometheus.Desc
46+
logger log.Logger
4547
}
4648

4749
type netDevStats map[string]map[string]uint64
@@ -90,23 +92,30 @@ func NewNetDevCollector(logger log.Logger) (Collector, error) {
9092
}, nil
9193
}
9294

95+
func (c *netDevCollector) metricDesc(key string) *prometheus.Desc {
96+
c.metricDescsMutex.Lock()
97+
defer c.metricDescsMutex.Unlock()
98+
99+
if _, ok := c.metricDescs[key]; !ok {
100+
c.metricDescs[key] = prometheus.NewDesc(
101+
prometheus.BuildFQName(namespace, c.subsystem, key+"_total"),
102+
fmt.Sprintf("Network device statistic %s.", key),
103+
[]string{"device"},
104+
nil,
105+
)
106+
}
107+
108+
return c.metricDescs[key]
109+
}
110+
93111
func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error {
94112
netDev, err := getNetDevStats(&c.deviceFilter, c.logger)
95113
if err != nil {
96114
return fmt.Errorf("couldn't get netstats: %w", err)
97115
}
98116
for dev, devStats := range netDev {
99117
for key, value := range devStats {
100-
desc, ok := c.metricDescs[key]
101-
if !ok {
102-
desc = prometheus.NewDesc(
103-
prometheus.BuildFQName(namespace, c.subsystem, key+"_total"),
104-
fmt.Sprintf("Network device statistic %s.", key),
105-
[]string{"device"},
106-
nil,
107-
)
108-
c.metricDescs[key] = desc
109-
}
118+
desc := c.metricDesc(key)
110119
ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(value), dev)
111120
}
112121
}

0 commit comments

Comments
 (0)