github.com/netdata/go.d.plugin@v0.58.1/pkg/prometheus/metric_series.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package prometheus
     4  
     5  import (
     6  	"sort"
     7  
     8  	"github.com/prometheus/prometheus/model/labels"
     9  )
    10  
    11  type (
    12  	// SeriesSample is a pair of label set and value
    13  	SeriesSample struct {
    14  		Labels labels.Labels
    15  		Value  float64
    16  	}
    17  
    18  	// Series is a list of SeriesSample
    19  	Series []SeriesSample
    20  )
    21  
    22  // Name the __name__ label value
    23  func (s SeriesSample) Name() string {
    24  	return s.Labels[0].Value
    25  }
    26  
    27  // Add appends a metric.
    28  func (s *Series) Add(kv SeriesSample) {
    29  	*s = append(*s, kv)
    30  }
    31  
    32  // Reset resets the buffer to be empty,
    33  // but it retains the underlying storage for use by future writes.
    34  func (s *Series) Reset() {
    35  	*s = (*s)[:0]
    36  }
    37  
    38  // Sort sorts data.
    39  func (s Series) Sort() {
    40  	sort.Sort(s)
    41  }
    42  
    43  // Len returns metric length.
    44  func (s Series) Len() int {
    45  	return len(s)
    46  }
    47  
    48  // Less reports whether the element with
    49  // index i should sort before the element with index j.
    50  func (s Series) Less(i, j int) bool {
    51  	return s[i].Name() < s[j].Name()
    52  }
    53  
    54  // Swap swaps the elements with indexes i and j.
    55  func (s Series) Swap(i, j int) {
    56  	s[i], s[j] = s[j], s[i]
    57  }
    58  
    59  // FindByName finds metrics where it's __name__ label matches given name.
    60  // It expects the metrics is sorted.
    61  // Complexity: O(log(N))
    62  func (s Series) FindByName(name string) Series {
    63  	from := sort.Search(len(s), func(i int) bool {
    64  		return s[i].Name() >= name
    65  	})
    66  	if from == len(s) || s[from].Name() != name { // not found
    67  		return Series{}
    68  	}
    69  	until := from + 1
    70  	for until < len(s) && s[until].Name() == name {
    71  		until++
    72  	}
    73  	return s[from:until]
    74  }
    75  
    76  // FindByNames finds metrics where it's __name__ label matches given any of names.
    77  // It expects the metrics is sorted.
    78  // Complexity: O(log(N))
    79  func (s Series) FindByNames(names ...string) Series {
    80  	switch len(names) {
    81  	case 0:
    82  		return Series{}
    83  	case 1:
    84  		return s.FindByName(names[0])
    85  	}
    86  	var result Series
    87  	for _, name := range names {
    88  		result = append(result, s.FindByName(name)...)
    89  	}
    90  	return result
    91  }
    92  
    93  // Max returns the max value.
    94  // It does NOT expect the metrics is sorted.
    95  // Complexity: O(N)
    96  func (s Series) Max() float64 {
    97  	switch len(s) {
    98  	case 0:
    99  		return 0
   100  	case 1:
   101  		return s[0].Value
   102  	}
   103  	max := s[0].Value
   104  	for _, kv := range s[1:] {
   105  		if max < kv.Value {
   106  			max = kv.Value
   107  		}
   108  	}
   109  	return max
   110  }