github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/stores/shipper/index/compactor/series.go (about) 1 package compactor 2 3 import ( 4 "github.com/prometheus/prometheus/model/labels" 5 "go.etcd.io/bbolt" 6 7 "github.com/grafana/loki/pkg/storage/config" 8 ) 9 10 type userSeries struct { 11 key []byte 12 seriesIDLen int 13 } 14 15 func newUserSeries(seriesID []byte, userID []byte) userSeries { 16 key := make([]byte, 0, len(seriesID)+len(userID)) 17 key = append(key, seriesID...) 18 key = append(key, userID...) 19 return userSeries{ 20 key: key, 21 seriesIDLen: len(seriesID), 22 } 23 } 24 25 func (us userSeries) Key() string { 26 return unsafeGetString(us.key) 27 } 28 29 func (us userSeries) SeriesID() []byte { 30 return us.key[:us.seriesIDLen] 31 } 32 33 func (us userSeries) UserID() []byte { 34 return us.key[us.seriesIDLen:] 35 } 36 37 func (us *userSeries) Reset(seriesID []byte, userID []byte) { 38 if us.key == nil { 39 us.key = make([]byte, 0, len(seriesID)+len(userID)) 40 } 41 us.key = us.key[:0] 42 us.key = append(us.key, seriesID...) 43 us.key = append(us.key, userID...) 44 us.seriesIDLen = len(seriesID) 45 } 46 47 type seriesLabels struct { 48 userSeries 49 lbs labels.Labels 50 } 51 52 type seriesLabelsMapper struct { 53 cursor *bbolt.Cursor 54 config config.PeriodConfig 55 56 bufKey userSeries 57 mapping map[string]*seriesLabels 58 } 59 60 func newSeriesLabelsMapper(bucket *bbolt.Bucket, config config.PeriodConfig) (*seriesLabelsMapper, error) { 61 sm := &seriesLabelsMapper{ 62 cursor: bucket.Cursor(), 63 mapping: map[string]*seriesLabels{}, 64 config: config, 65 bufKey: newUserSeries(nil, nil), 66 } 67 if err := sm.build(); err != nil { 68 return nil, err 69 } 70 return sm, nil 71 } 72 73 func (sm *seriesLabelsMapper) Get(seriesID []byte, userID []byte) labels.Labels { 74 sm.bufKey.Reset(seriesID, userID) 75 lbs, ok := sm.mapping[sm.bufKey.Key()] 76 if ok { 77 return lbs.lbs 78 } 79 return labels.Labels{} 80 } 81 82 func (sm *seriesLabelsMapper) build() error { 83 Outer: 84 for k, v := sm.cursor.First(); k != nil; k, v = sm.cursor.Next() { 85 ref, ok, err := parseLabelSeriesRangeKey(decodeKey(k)) 86 if err != nil { 87 return err 88 } 89 if !ok { 90 continue 91 } 92 sm.bufKey.Reset(ref.SeriesID, ref.UserID) 93 lbs, ok := sm.mapping[sm.bufKey.Key()] 94 if !ok { 95 k := newUserSeries(ref.SeriesID, ref.UserID) 96 lbs = &seriesLabels{ 97 userSeries: k, 98 lbs: make(labels.Labels, 0, 15), 99 } 100 sm.mapping[k.Key()] = lbs 101 } 102 // add the labels if it doesn't exist. 103 for _, l := range lbs.lbs { 104 if l.Name == unsafeGetString(ref.Name) { 105 continue Outer 106 } 107 } 108 lbs.lbs = append(lbs.lbs, labels.Label{Name: string(ref.Name), Value: string(v)}) 109 } 110 return nil 111 }