github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/ingester/index/multi.go (about) 1 package index 2 3 import ( 4 "time" 5 6 "github.com/pkg/errors" 7 "github.com/prometheus/common/model" 8 "github.com/prometheus/prometheus/model/labels" 9 10 "github.com/grafana/loki/pkg/logproto" 11 "github.com/grafana/loki/pkg/querier/astmapper" 12 "github.com/grafana/loki/pkg/storage/config" 13 ) 14 15 type periodIndex struct { 16 time.Time 17 idx int // address of the index to use 18 } 19 20 type Multi struct { 21 periods []periodIndex 22 indices []Interface 23 } 24 25 func NewMultiInvertedIndex(periods []config.PeriodConfig, indexShards uint32) (*Multi, error) { 26 var ( 27 err error 28 29 ii Interface // always stored in 0th index 30 bitPrefixed Interface // always stored in 1st index 31 32 periodIndices []periodIndex 33 ) 34 35 for _, pd := range periods { 36 switch pd.IndexType { 37 case config.TSDBType: 38 if bitPrefixed == nil { 39 bitPrefixed, err = NewBitPrefixWithShards(indexShards) 40 if err != nil { 41 return nil, errors.Wrapf(err, "creating tsdb inverted index for period starting %v", pd.From) 42 } 43 } 44 periodIndices = append(periodIndices, periodIndex{ 45 Time: pd.From.Time.Time(), 46 idx: 1, // tsdb inverted index is always stored in position one 47 }) 48 default: 49 if ii == nil { 50 ii = NewWithShards(indexShards) 51 } 52 periodIndices = append(periodIndices, periodIndex{ 53 Time: pd.From.Time.Time(), 54 idx: 0, // regular inverted index is always stored in position zero 55 }) 56 } 57 } 58 59 return &Multi{ 60 periods: periodIndices, 61 indices: []Interface{ii, bitPrefixed}, 62 }, nil 63 } 64 65 func (m *Multi) Add(labels []logproto.LabelAdapter, fp model.Fingerprint) (result labels.Labels) { 66 for _, i := range m.indices { 67 if i != nil { 68 result = i.Add(labels, fp) 69 } 70 } 71 return 72 } 73 74 func (m *Multi) Delete(labels labels.Labels, fp model.Fingerprint) { 75 for _, i := range m.indices { 76 if i != nil { 77 i.Delete(labels, fp) 78 } 79 } 80 81 } 82 83 func (m *Multi) Lookup(t time.Time, matchers []*labels.Matcher, shard *astmapper.ShardAnnotation) ([]model.Fingerprint, error) { 84 return m.indexFor(t).Lookup(matchers, shard) 85 } 86 87 func (m *Multi) LabelNames(t time.Time, shard *astmapper.ShardAnnotation) ([]string, error) { 88 return m.indexFor(t).LabelNames(shard) 89 } 90 91 func (m *Multi) LabelValues(t time.Time, name string, shard *astmapper.ShardAnnotation) ([]string, error) { 92 return m.indexFor(t).LabelValues(name, shard) 93 } 94 95 // Query planning is responsible for ensuring no query spans more than one inverted index. 96 // Therefore we don't need to account for both `from` and `through`. 97 func (m *Multi) indexFor(t time.Time) Interface { 98 for i := range m.periods { 99 if !m.periods[i].Time.After(t) && (i+1 == len(m.periods) || t.Before(m.periods[i+1].Time)) { 100 return m.indices[m.periods[i].idx] 101 } 102 } 103 return noopInvertedIndex{} 104 } 105 106 type noopInvertedIndex struct{} 107 108 func (noopInvertedIndex) Add(labels []logproto.LabelAdapter, fp model.Fingerprint) labels.Labels { 109 return nil 110 } 111 112 func (noopInvertedIndex) Delete(labels labels.Labels, fp model.Fingerprint) {} 113 114 func (noopInvertedIndex) Lookup(matchers []*labels.Matcher, shard *astmapper.ShardAnnotation) ([]model.Fingerprint, error) { 115 return nil, nil 116 } 117 118 func (noopInvertedIndex) LabelNames(shard *astmapper.ShardAnnotation) ([]string, error) { 119 return nil, nil 120 } 121 122 func (noopInvertedIndex) LabelValues(name string, shard *astmapper.ShardAnnotation) ([]string, error) { 123 return nil, nil 124 }