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  }