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 (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,36 +78,50 @@ type Summary interface {
|
|||||||
UpdateDuration(time.Time)
|
UpdateDuration(time.Time)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sort labels alphabeticaly by label name
|
||||||
type byKey []string
|
type byKey []string
|
||||||
|
|
||||||
func (k byKey) Len() int { return len(k) / 2 }
|
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) Less(i, j int) bool { return k[i*2] < k[j*2] }
|
||||||
func (k byKey) Swap(i, j int) {
|
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) {
|
// BuildName used to combine metric with labels.
|
||||||
bk := byKey(*slice)
|
// If labels count is odd, drop last element
|
||||||
if bk.Len() <= 1 {
|
func BuildName(name string, labels ...string) string {
|
||||||
return
|
if len(labels)%2 == 1 {
|
||||||
|
labels = labels[:len(labels)-1]
|
||||||
}
|
}
|
||||||
sort.Sort(bk)
|
|
||||||
v := reflect.ValueOf(slice).Elem()
|
sort.Sort(byKey(labels))
|
||||||
cnt := 0
|
|
||||||
key := 0
|
idx := 0
|
||||||
val := 1
|
for {
|
||||||
for key < v.Len() {
|
if labels[idx] == labels[idx+2] {
|
||||||
if len(bk) > key+2 && bk[key] == bk[key+2] {
|
copy(labels[idx:], labels[idx+2:])
|
||||||
key += 2
|
labels = labels[:len(labels)-2]
|
||||||
val += 2
|
} else {
|
||||||
continue
|
idx += 2
|
||||||
}
|
}
|
||||||
v.Index(cnt).Set(v.Index(key))
|
if idx+2 >= len(labels) {
|
||||||
cnt++
|
break
|
||||||
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()
|
cnt.Inc()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLabelsSort(t *testing.T) {
|
func TestBuildName(t *testing.T) {
|
||||||
ls := []string{"server", "http", "register", "mdns", "broker", "broker1", "broker", "broker2", "server", "tcp"}
|
data := map[string][]string{
|
||||||
Sort(&ls)
|
// `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" {
|
for e, d := range data {
|
||||||
t.Fatalf("sort error: %v", ls)
|
if x := BuildName(d[0], d[1:]...); x != e {
|
||||||
|
t.Fatalf("expect: %s, result: %s", e, x)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user