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  }