netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/pkg/prometheus/metric_series.go

Summary

Maintainability
A
0 mins
Test Coverage
// SPDX-License-Identifier: GPL-3.0-or-later

package prometheus

import (
    "sort"

    "github.com/prometheus/prometheus/model/labels"
)

type (
    // SeriesSample is a pair of label set and value
    SeriesSample struct {
        Labels labels.Labels
        Value  float64
    }

    // Series is a list of SeriesSample
    Series []SeriesSample
)

// Name the __name__ label value
func (s SeriesSample) Name() string {
    return s.Labels[0].Value
}

// Add appends a metric.
func (s *Series) Add(kv SeriesSample) {
    *s = append(*s, kv)
}

// Reset resets the buffer to be empty,
// but it retains the underlying storage for use by future writes.
func (s *Series) Reset() {
    *s = (*s)[:0]
}

// Sort sorts data.
func (s Series) Sort() {
    sort.Sort(s)
}

// Len returns metric length.
func (s Series) Len() int {
    return len(s)
}

// Less reports whether the element with
// index i should sort before the element with index j.
func (s Series) Less(i, j int) bool {
    return s[i].Name() < s[j].Name()
}

// Swap swaps the elements with indexes i and j.
func (s Series) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}

// FindByName finds metrics where it's __name__ label matches given name.
// It expects the metrics is sorted.
// Complexity: O(log(N))
func (s Series) FindByName(name string) Series {
    from := sort.Search(len(s), func(i int) bool {
        return s[i].Name() >= name
    })
    if from == len(s) || s[from].Name() != name { // not found
        return Series{}
    }
    until := from + 1
    for until < len(s) && s[until].Name() == name {
        until++
    }
    return s[from:until]
}

// FindByNames finds metrics where it's __name__ label matches given any of names.
// It expects the metrics is sorted.
// Complexity: O(log(N))
func (s Series) FindByNames(names ...string) Series {
    switch len(names) {
    case 0:
        return Series{}
    case 1:
        return s.FindByName(names[0])
    }
    var result Series
    for _, name := range names {
        result = append(result, s.FindByName(name)...)
    }
    return result
}

// Max returns the max value.
// It does NOT expect the metrics is sorted.
// Complexity: O(N)
func (s Series) Max() float64 {
    switch len(s) {
    case 0:
        return 0
    case 1:
        return s[0].Value
    }
    max := s[0].Value
    for _, kv := range s[1:] {
        if max < kv.Value {
            max = kv.Value
        }
    }
    return max
}