meter: BuildName func to combine metric name with labels into string
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
7ece08896f
commit
c6ba2a91e6
@ -3,8 +3,9 @@ package meter
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -77,36 +78,50 @@ type Summary interface {
|
||||
UpdateDuration(time.Time)
|
||||
}
|
||||
|
||||
// sort labels alphabeticaly by label name
|
||||
type byKey []string
|
||||
|
||||
func (k byKey) Len() int { return len(k) / 2 }
|
||||
func (k byKey) Less(i, j int) bool { return k[i*2] < k[j*2] }
|
||||
func (k byKey) Swap(i, j int) {
|
||||
k[i*2], k[i*2+1], k[j*2], k[j*2+1] = k[j*2], k[j*2+1], k[i*2], k[i*2+1]
|
||||
k[i*2], k[j*2] = k[j*2], k[i*2]
|
||||
k[i*2+1], k[j*2+1] = k[j*2+1], k[i*2+1]
|
||||
}
|
||||
|
||||
func Sort(slice *[]string) {
|
||||
bk := byKey(*slice)
|
||||
if bk.Len() <= 1 {
|
||||
return
|
||||
// BuildName used to combine metric with labels.
|
||||
// If labels count is odd, drop last element
|
||||
func BuildName(name string, labels ...string) string {
|
||||
if len(labels)%2 == 1 {
|
||||
labels = labels[:len(labels)-1]
|
||||
}
|
||||
sort.Sort(bk)
|
||||
v := reflect.ValueOf(slice).Elem()
|
||||
cnt := 0
|
||||
key := 0
|
||||
val := 1
|
||||
for key < v.Len() {
|
||||
if len(bk) > key+2 && bk[key] == bk[key+2] {
|
||||
key += 2
|
||||
val += 2
|
||||
continue
|
||||
|
||||
sort.Sort(byKey(labels))
|
||||
|
||||
idx := 0
|
||||
for {
|
||||
if labels[idx] == labels[idx+2] {
|
||||
copy(labels[idx:], labels[idx+2:])
|
||||
labels = labels[:len(labels)-2]
|
||||
} else {
|
||||
idx += 2
|
||||
}
|
||||
if idx+2 >= len(labels) {
|
||||
break
|
||||
}
|
||||
v.Index(cnt).Set(v.Index(key))
|
||||
cnt++
|
||||
v.Index(cnt).Set(v.Index(val))
|
||||
cnt++
|
||||
key += 2
|
||||
val += 2
|
||||
}
|
||||
v.SetLen(cnt)
|
||||
|
||||
var b strings.Builder
|
||||
_, _ = b.WriteString(name)
|
||||
_, _ = b.WriteRune('{')
|
||||
for idx := 0; idx < len(labels); idx += 2 {
|
||||
if idx > 0 {
|
||||
_, _ = b.WriteRune(',')
|
||||
}
|
||||
_, _ = b.WriteString(labels[idx])
|
||||
_, _ = b.WriteString(`=`)
|
||||
_, _ = b.WriteString(strconv.Quote(labels[idx+1]))
|
||||
}
|
||||
_, _ = b.WriteRune('}')
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
@ -14,11 +14,21 @@ func TestNoopMeter(t *testing.T) {
|
||||
cnt.Inc()
|
||||
}
|
||||
|
||||
func TestLabelsSort(t *testing.T) {
|
||||
ls := []string{"server", "http", "register", "mdns", "broker", "broker1", "broker", "broker2", "server", "tcp"}
|
||||
Sort(&ls)
|
||||
func TestBuildName(t *testing.T) {
|
||||
data := map[string][]string{
|
||||
// `my_metric{firstlabel="value2",zerolabel="value3"}`: []string{
|
||||
// "my_metric",
|
||||
// "zerolabel", "value3", "firstlabel", "value2",
|
||||
// },
|
||||
`my_metric{broker="broker2",register="mdns",server="tcp"}`: []string{
|
||||
"my_metric",
|
||||
"broker", "broker1", "broker", "broker2", "server", "http", "server", "tcp", "register", "mdns",
|
||||
},
|
||||
}
|
||||
|
||||
if ls[0] != "broker" || ls[1] != "broker2" {
|
||||
t.Fatalf("sort error: %v", ls)
|
||||
for e, d := range data {
|
||||
if x := BuildName(d[0], d[1:]...); x != e {
|
||||
t.Fatalf("expect: %s, result: %s", e, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user