github.com/grafana/pyroscope@v1.18.0/pkg/model/labels_merger.go (about) 1 package model 2 3 import ( 4 "slices" 5 "sort" 6 "sync" 7 8 typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1" 9 ) 10 11 type LabelMerger struct { 12 mu sync.Mutex 13 names map[string]struct{} 14 values map[string]struct{} 15 series map[uint64]*typesv1.Labels 16 } 17 18 func NewLabelMerger() *LabelMerger { 19 return &LabelMerger{ 20 names: make(map[string]struct{}), 21 values: make(map[string]struct{}), 22 series: make(map[uint64]*typesv1.Labels), 23 } 24 } 25 26 func (m *LabelMerger) MergeLabelNames(names []string) { 27 m.mu.Lock() 28 defer m.mu.Unlock() 29 for _, n := range names { 30 m.names[n] = struct{}{} 31 } 32 } 33 34 func (m *LabelMerger) MergeLabelValues(values []string) { 35 m.mu.Lock() 36 defer m.mu.Unlock() 37 for _, v := range values { 38 m.values[v] = struct{}{} 39 } 40 } 41 42 func (m *LabelMerger) HasNames() bool { 43 return len(m.names) > 0 44 } 45 46 func (m *LabelMerger) LabelNames() []string { 47 m.mu.Lock() 48 defer m.mu.Unlock() 49 s := make([]string, len(m.names)) 50 var i int 51 for n := range m.names { 52 s[i] = n 53 i++ 54 } 55 sort.Strings(s) 56 return s 57 } 58 59 func (m *LabelMerger) HasValues() bool { 60 return len(m.values) > 0 61 } 62 63 func (m *LabelMerger) LabelValues() []string { 64 m.mu.Lock() 65 defer m.mu.Unlock() 66 s := make([]string, len(m.values)) 67 var i int 68 for v := range m.values { 69 s[i] = v 70 i++ 71 } 72 sort.Strings(s) 73 return s 74 } 75 76 func (m *LabelMerger) MergeSeries(series []*typesv1.Labels) { 77 m.mu.Lock() 78 defer m.mu.Unlock() 79 for _, s := range series { 80 m.series[Labels(s.Labels).Hash()] = s 81 } 82 } 83 84 func (m *LabelMerger) MergeLabels(ls []Labels) { 85 m.mu.Lock() 86 defer m.mu.Unlock() 87 for _, l := range ls { 88 m.series[l.Hash()] = &typesv1.Labels{Labels: l} 89 } 90 } 91 92 func (m *LabelMerger) Labels() []*typesv1.Labels { 93 m.mu.Lock() 94 defer m.mu.Unlock() 95 s := make([]*typesv1.Labels, len(m.series)) 96 var i int 97 for _, v := range m.series { 98 s[i] = v 99 i++ 100 } 101 slices.SortFunc(s, func(a, b *typesv1.Labels) int { 102 return CompareLabelPairs(a.Labels, b.Labels) 103 }) 104 return s 105 } 106 107 func (m *LabelMerger) HasSeries() bool { 108 return len(m.series) > 0 109 }