github.com/thanos-io/thanos@v0.32.5/internal/cortex/querier/series/series_set.go (about) 1 // Copyright (c) The Cortex Authors. 2 // Licensed under the Apache License 2.0. 3 4 // Some of the code in this file was adapted from Prometheus (https://github.com/prometheus/prometheus). 5 // The original license header is included below: 6 // 7 // Copyright 2017 The Prometheus Authors 8 // Licensed under the Apache License, Version 2.0 (the "License"); 9 // you may not use this file except in compliance with the License. 10 // You may obtain a copy of the License at 11 // 12 // http://www.apache.org/licenses/LICENSE-2.0 13 // 14 // Unless required by applicable law or agreed to in writing, software 15 // distributed under the License is distributed on an "AS IS" BASIS, 16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 // See the License for the specific language governing permissions and 18 // limitations under the License. 19 20 package series 21 22 import ( 23 "sort" 24 25 "github.com/prometheus/common/model" 26 "github.com/prometheus/prometheus/model/histogram" 27 "github.com/prometheus/prometheus/model/labels" 28 "github.com/prometheus/prometheus/storage" 29 "github.com/prometheus/prometheus/tsdb/chunkenc" 30 ) 31 32 // ConcreteSeriesSet implements storage.SeriesSet. 33 type ConcreteSeriesSet struct { 34 cur int 35 series []storage.Series 36 } 37 38 // NewConcreteSeriesSet instantiates an in-memory series set from a series 39 // Series will be sorted by labels. 40 func NewConcreteSeriesSet(series []storage.Series) storage.SeriesSet { 41 sort.Sort(byLabels(series)) 42 return &ConcreteSeriesSet{ 43 cur: -1, 44 series: series, 45 } 46 } 47 48 // Next iterates through a series set and implements storage.SeriesSet. 49 func (c *ConcreteSeriesSet) Next() bool { 50 c.cur++ 51 return c.cur < len(c.series) 52 } 53 54 // At returns the current series and implements storage.SeriesSet. 55 func (c *ConcreteSeriesSet) At() storage.Series { 56 return c.series[c.cur] 57 } 58 59 // Err implements storage.SeriesSet. 60 func (c *ConcreteSeriesSet) Err() error { 61 return nil 62 } 63 64 // Warnings implements storage.SeriesSet. 65 func (c *ConcreteSeriesSet) Warnings() storage.Warnings { 66 return nil 67 } 68 69 // ConcreteSeries implements storage.Series. 70 type ConcreteSeries struct { 71 labels labels.Labels 72 samples []model.SamplePair 73 } 74 75 // NewConcreteSeries instantiates an in memory series from a list of samples & labels 76 func NewConcreteSeries(ls labels.Labels, samples []model.SamplePair) *ConcreteSeries { 77 return &ConcreteSeries{ 78 labels: ls, 79 samples: samples, 80 } 81 } 82 83 // Labels implements storage.Series 84 func (c *ConcreteSeries) Labels() labels.Labels { 85 return c.labels 86 } 87 88 // Iterator implements storage.Series 89 func (c *ConcreteSeries) Iterator(chunkenc.Iterator) chunkenc.Iterator { 90 return NewConcreteSeriesIterator(c) 91 } 92 93 // concreteSeriesIterator implements chunkenc.Iterator. 94 type concreteSeriesIterator struct { 95 cur int 96 series *ConcreteSeries 97 } 98 99 // NewConcreteSeriesIterator instaniates an in memory chunkenc.Iterator 100 func NewConcreteSeriesIterator(series *ConcreteSeries) chunkenc.Iterator { 101 return &concreteSeriesIterator{ 102 cur: -1, 103 series: series, 104 } 105 } 106 107 // TODO(rabenhorst): Native histogram support needs to be added, float type is hardcoded. 108 func (c *concreteSeriesIterator) Seek(t int64) chunkenc.ValueType { 109 c.cur = sort.Search(len(c.series.samples), func(n int) bool { 110 return c.series.samples[n].Timestamp >= model.Time(t) 111 }) 112 113 if c.cur < len(c.series.samples) { 114 return chunkenc.ValFloat 115 } 116 117 return chunkenc.ValNone 118 } 119 120 func (c *concreteSeriesIterator) At() (t int64, v float64) { 121 s := c.series.samples[c.cur] 122 return int64(s.Timestamp), float64(s.Value) 123 } 124 125 // TODO(rabenhorst): Needs to be implemented for native histogram support. 126 func (c *concreteSeriesIterator) AtHistogram() (int64, *histogram.Histogram) { 127 panic("not implemented") 128 } 129 130 func (c *concreteSeriesIterator) AtFloatHistogram() (int64, *histogram.FloatHistogram) { 131 panic("not implemented") 132 } 133 134 func (c *concreteSeriesIterator) AtT() int64 { 135 t, _ := c.At() 136 return t 137 } 138 139 func (c *concreteSeriesIterator) Next() chunkenc.ValueType { 140 c.cur++ 141 142 if c.cur < len(c.series.samples) { 143 return chunkenc.ValFloat 144 } 145 146 return chunkenc.ValNone 147 } 148 149 func (c *concreteSeriesIterator) Err() error { 150 return nil 151 } 152 153 // NewErrIterator instantiates an errIterator 154 func NewErrIterator(err error) chunkenc.Iterator { 155 return errIterator{err} 156 } 157 158 // errIterator implements chunkenc.Iterator, just returning an error. 159 type errIterator struct { 160 err error 161 } 162 163 func (errIterator) Seek(int64) chunkenc.ValueType { 164 return chunkenc.ValNone 165 } 166 167 func (errIterator) Next() chunkenc.ValueType { 168 return chunkenc.ValNone 169 } 170 171 func (errIterator) At() (t int64, v float64) { 172 return 0, 0 173 } 174 175 func (errIterator) AtHistogram() (int64, *histogram.Histogram) { 176 return 0, nil 177 } 178 179 func (errIterator) AtFloatHistogram() (int64, *histogram.FloatHistogram) { 180 return 0, nil 181 } 182 183 func (errIterator) AtT() int64 { 184 return 0 185 } 186 187 func (e errIterator) Err() error { 188 return e.err 189 } 190 191 // MatrixToSeriesSet creates a storage.SeriesSet from a model.Matrix 192 // Series will be sorted by labels. 193 func MatrixToSeriesSet(m model.Matrix) storage.SeriesSet { 194 series := make([]storage.Series, 0, len(m)) 195 for _, ss := range m { 196 series = append(series, &ConcreteSeries{ 197 labels: metricToLabels(ss.Metric), 198 samples: ss.Values, 199 }) 200 } 201 return NewConcreteSeriesSet(series) 202 } 203 204 func metricToLabels(m model.Metric) labels.Labels { 205 ls := make(labels.Labels, 0, len(m)) 206 for k, v := range m { 207 ls = append(ls, labels.Label{ 208 Name: string(k), 209 Value: string(v), 210 }) 211 } 212 // PromQL expects all labels to be sorted! In general, anyone constructing 213 // a labels.Labels list is responsible for sorting it during construction time. 214 sort.Sort(ls) 215 return ls 216 } 217 218 type byLabels []storage.Series 219 220 func (b byLabels) Len() int { return len(b) } 221 func (b byLabels) Swap(i, j int) { b[i], b[j] = b[j], b[i] } 222 func (b byLabels) Less(i, j int) bool { return labels.Compare(b[i].Labels(), b[j].Labels()) < 0 } 223 224 type DeletedSeriesIterator struct { 225 itr chunkenc.Iterator 226 deletedIntervals []model.Interval 227 } 228 229 func NewDeletedSeriesIterator(itr chunkenc.Iterator, deletedIntervals []model.Interval) chunkenc.Iterator { 230 return &DeletedSeriesIterator{ 231 itr: itr, 232 deletedIntervals: deletedIntervals, 233 } 234 } 235 236 // TODO(rabenhorst): Native histogram support needs to be added, float type is hardcoded. 237 func (d DeletedSeriesIterator) Seek(t int64) chunkenc.ValueType { 238 if valueType := d.itr.Seek(t); valueType == chunkenc.ValNone { 239 return valueType 240 } 241 242 seekedTs, _ := d.itr.At() 243 if d.isDeleted(seekedTs) { 244 // point we have seeked into is deleted, Next() should find a new non-deleted sample which is after t and seekedTs 245 return d.Next() 246 } 247 248 return chunkenc.ValFloat 249 } 250 251 func (d DeletedSeriesIterator) At() (t int64, v float64) { 252 return d.itr.At() 253 } 254 255 // TODO(rabenhorst): Needs to be implemented for native histogram support. 256 func (d DeletedSeriesIterator) AtHistogram() (int64, *histogram.Histogram) { 257 panic("not implemented") 258 } 259 260 func (d DeletedSeriesIterator) AtFloatHistogram() (int64, *histogram.FloatHistogram) { 261 panic("not implemented") 262 } 263 264 func (d DeletedSeriesIterator) AtT() int64 { 265 t, _ := d.itr.At() 266 return t 267 } 268 269 func (d DeletedSeriesIterator) Next() chunkenc.ValueType { 270 for valueType := d.itr.Next(); valueType != chunkenc.ValNone; valueType = d.itr.Next() { 271 ts, _ := d.itr.At() 272 273 if d.isDeleted(ts) { 274 continue 275 } 276 return valueType 277 } 278 return chunkenc.ValNone 279 } 280 281 func (d DeletedSeriesIterator) Err() error { 282 return d.itr.Err() 283 } 284 285 // isDeleted removes intervals which are past ts while checking for whether ts happens to be in one of the deleted intervals 286 func (d *DeletedSeriesIterator) isDeleted(ts int64) bool { 287 mts := model.Time(ts) 288 289 for _, interval := range d.deletedIntervals { 290 if mts > interval.End { 291 d.deletedIntervals = d.deletedIntervals[1:] 292 continue 293 } else if mts < interval.Start { 294 return false 295 } 296 297 return true 298 } 299 300 return false 301 }