Skip to content

Commit

Permalink
fix metric sort error
Browse files Browse the repository at this point in the history
Signed-off-by: heyitao <heyitao@uniontech.com>
  • Loading branch information
heyitao committed Mar 5, 2024
1 parent b59cfc9 commit 1d8e814
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
19 changes: 18 additions & 1 deletion prometheus/internal/metric.go
Expand Up @@ -14,7 +14,9 @@
package internal

import (
"regexp"
"sort"
"strconv"

dto "github.com/prometheus/client_model/go"
)
Expand Down Expand Up @@ -46,6 +48,21 @@ func (s MetricSorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}

func (s MetricSorter) compare(si, sj string) bool {
// When the number of devices exceeds two digits, a sorting error occurs.
// dealing with sorting problems, especially CPU sorting errors
re := regexp.MustCompile(`\d+$`)
if re.Match([]byte(si)) && re.Match([]byte(sj)) {
siCode := re.FindStringSubmatch(si)[0]
sjCode := re.FindStringSubmatch(sj)[0]
siValue, _ := strconv.Atoi(siCode)
sjValue, _ := strconv.Atoi(sjCode)
return siValue < sjValue
}
// Non-numeric identification device, use original sorting
return si < sj
}

func (s MetricSorter) Less(i, j int) bool {
if len(s[i].Label) != len(s[j].Label) {
// This should not happen. The metrics are
Expand All @@ -60,7 +77,7 @@ func (s MetricSorter) Less(i, j int) bool {
vi := lp.GetValue()
vj := s[j].Label[n].GetValue()
if vi != vj {
return vi < vj
return s.compare(vi, vj)
}
}

Expand Down
68 changes: 68 additions & 0 deletions prometheus/internal/metric_sort_test.go
@@ -0,0 +1,68 @@
// Copyright 2022 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package internal

import (
"sort"
"strings"
"testing"

"github.com/prometheus/common/expfmt"
)

func BenchmarkSort(b *testing.B) {
var parser expfmt.TextParser
text := `
# HELP node_cpu_guest_seconds_total Seconds the CPUs spent in guests (VMs) for each mode.
# TYPE node_cpu_guest_seconds_total counter
node_cpu_guest_seconds_total{cpu="0",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="0",mode="user"} 0
node_cpu_guest_seconds_total{cpu="1",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="1",mode="user"} 0
node_cpu_guest_seconds_total{cpu="10",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="10",mode="user"} 0
node_cpu_guest_seconds_total{cpu="11",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="11",mode="user"} 0
node_cpu_guest_seconds_total{cpu="12",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="12",mode="user"} 0
node_cpu_guest_seconds_total{cpu="13",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="13",mode="user"} 0
node_cpu_guest_seconds_total{cpu="14",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="14",mode="user"} 0
node_cpu_guest_seconds_total{cpu="15",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="15",mode="user"} 0
node_cpu_guest_seconds_total{cpu="2",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="2",mode="user"} 0
node_cpu_guest_seconds_total{cpu="3",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="3",mode="user"} 0
node_cpu_guest_seconds_total{cpu="4",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="4",mode="user"} 0
node_cpu_guest_seconds_total{cpu="5",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="5",mode="user"} 0
node_cpu_guest_seconds_total{cpu="6",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="6",mode="user"} 0
node_cpu_guest_seconds_total{cpu="7",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="7",mode="user"} 0
node_cpu_guest_seconds_total{cpu="8",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="8",mode="user"} 0
node_cpu_guest_seconds_total{cpu="9",mode="nice"} 0
node_cpu_guest_seconds_total{cpu="9",mode="user"} 0
`
notNormalized, _ := parser.TextToMetricFamilies(strings.NewReader(text))
//NormalizeMetricFamilies(notNormalized)

Check failure on line 62 in prometheus/internal/metric_sort_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed with `-extra` (gofumpt)
for i := 0; i < b.N; i++ {
for _, mf := range notNormalized {
sort.Sort(MetricSorter(mf.Metric))
}
}
}

0 comments on commit 1d8e814

Please sign in to comment.