Skip to content

Commit

Permalink
ethtool: Prevent duplicate metric names (#2187)
Browse files Browse the repository at this point in the history
Sanitizing the metric names can lead to duplicate metric names:

```
caller=level.go:63 level=error caller="error gathering metrics: [from Gatherer #2] collected metric \"node_ethtool_giant_hdr\" { label:<name:\"device\" value:\"ens192\" > untyped:<value:0" msg=" > } was collected before with the same name and label values"
```

Generate a map from the sanitized metric names to the metric names from
ethtool. In case of duplicate sanitized metric names drop both metrics,
because it is unknown which one to take.

Fixes: #2185
Signed-off-by: Benjamin Drung <benjamin.drung@ionos.com>
  • Loading branch information
bdrung authored Nov 15, 2021
1 parent 58ab014 commit d85cbaa
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 5 deletions.
30 changes: 25 additions & 5 deletions collector/ethtool_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,19 +385,39 @@ func (c *ethtoolCollector) Update(ch chan<- prometheus.Metric) error {
continue
}

// Sanitizing the metric names can lead to duplicate metric names. Therefore check for clashes beforehand.
metricFQNames := make(map[string]string)
for metric := range stats {
if !c.metricsPattern.MatchString(metric) {
continue
}
metricFQName := buildEthtoolFQName(metric)
existingMetric, exists := metricFQNames[metricFQName]
if exists {
level.Debug(c.logger).Log("msg", "dropping duplicate metric name", "device", device,
"metricFQName", metricFQName, "metric1", existingMetric, "metric2", metric)
// Keep the metric as "deleted" in the dict in case there are 3 duplicates.
metricFQNames[metricFQName] = ""
} else {
metricFQNames[metricFQName] = metric
}
}

// Sort metric names so that the test fixtures will match up
keys := make([]string, 0, len(stats))
for k := range stats {
keys := make([]string, 0, len(metricFQNames))
for k := range metricFQNames {
keys = append(keys, k)
}
sort.Strings(keys)

for _, metric := range keys {
if !c.metricsPattern.MatchString(metric) {
for _, metricFQName := range keys {
metric := metricFQNames[metricFQName]
if metric == "" {
// Skip the "deleted" duplicate metrics
continue
}

val := stats[metric]
metricFQName := buildEthtoolFQName(metric)

// Check to see if this metric exists; if not then create it and store it in c.entries.
entry, exists := c.entries[metric]
Expand Down
2 changes: 2 additions & 0 deletions collector/fixtures/ethtool/eth0/statistics
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ NIC statistics:
rx_multicast: 23973
tx_aborted: 0
tx_underrun: 0
duplicate metric: 1
duplicate_metric: 2

0 comments on commit d85cbaa

Please sign in to comment.