Skip to content

Commit

Permalink
netdev_common: Add mutex around metricDescs access
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
bison committed Mar 16, 2022
1 parent 996563f commit cb7b5a7
Showing 1 changed file with 23 additions and 14 deletions.
37 changes: 23 additions & 14 deletions collector/netdev_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"net"
"strconv"
"sync"

"github.com/go-kit/log"
"github.com/go-kit/log/level"
Expand All @@ -38,10 +39,11 @@ var (
)

type netDevCollector struct {
subsystem string
deviceFilter netDevFilter
metricDescs map[string]*prometheus.Desc
logger log.Logger
subsystem string
deviceFilter netDevFilter
metricDescsMutex sync.Mutex
metricDescs map[string]*prometheus.Desc
logger log.Logger
}

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

func (c *netDevCollector) metricDesc(key string) *prometheus.Desc {
c.metricDescsMutex.Lock()
defer c.metricDescsMutex.Unlock()

if _, ok := c.metricDescs[key]; !ok {
c.metricDescs[key] = prometheus.NewDesc(
prometheus.BuildFQName(namespace, c.subsystem, key+"_total"),
fmt.Sprintf("Network device statistic %s.", key),
[]string{"device"},
nil,
)
}

return c.metricDescs[key]
}

func (c *netDevCollector) Update(ch chan<- prometheus.Metric) error {
netDev, err := getNetDevStats(&c.deviceFilter, c.logger)
if err != nil {
return fmt.Errorf("couldn't get netstats: %w", err)
}
for dev, devStats := range netDev {
for key, value := range devStats {
desc, ok := c.metricDescs[key]
if !ok {
desc = prometheus.NewDesc(
prometheus.BuildFQName(namespace, c.subsystem, key+"_total"),
fmt.Sprintf("Network device statistic %s.", key),
[]string{"device"},
nil,
)
c.metricDescs[key] = desc
}
desc := c.metricDesc(key)
ch <- prometheus.MustNewConstMetric(desc, prometheus.CounterValue, float64(value), dev)
}
}
Expand Down

0 comments on commit cb7b5a7

Please sign in to comment.