Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
		
							
								
								
									
										14
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/labelvalues.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/labelvalues.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
package lv
 | 
			
		||||
 | 
			
		||||
// LabelValues is a type alias that provides validation on its With method.
 | 
			
		||||
// Metrics may include it as a member to help them satisfy With semantics and
 | 
			
		||||
// save some code duplication.
 | 
			
		||||
type LabelValues []string
 | 
			
		||||
 | 
			
		||||
// With validates the input, and returns a new aggregate labelValues.
 | 
			
		||||
func (lvs LabelValues) With(labelValues ...string) LabelValues {
 | 
			
		||||
	if len(labelValues)%2 != 0 {
 | 
			
		||||
		labelValues = append(labelValues, "unknown")
 | 
			
		||||
	}
 | 
			
		||||
	return append(lvs, labelValues...)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/labelvalues_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/labelvalues_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
package lv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestWith(t *testing.T) {
 | 
			
		||||
	var a LabelValues
 | 
			
		||||
	b := a.With("a", "1")
 | 
			
		||||
	c := a.With("b", "2", "c", "3")
 | 
			
		||||
 | 
			
		||||
	if want, have := "", strings.Join(a, ""); want != have {
 | 
			
		||||
		t.Errorf("With appears to mutate the original LabelValues: want %q, have %q", want, have)
 | 
			
		||||
	}
 | 
			
		||||
	if want, have := "a1", strings.Join(b, ""); want != have {
 | 
			
		||||
		t.Errorf("With does not appear to return the right thing: want %q, have %q", want, have)
 | 
			
		||||
	}
 | 
			
		||||
	if want, have := "b2c3", strings.Join(c, ""); want != have {
 | 
			
		||||
		t.Errorf("With does not appear to return the right thing: want %q, have %q", want, have)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										145
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/space.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/space.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
			
		||||
package lv
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
// NewSpace returns an N-dimensional vector space.
 | 
			
		||||
func NewSpace() *Space {
 | 
			
		||||
	return &Space{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Space represents an N-dimensional vector space. Each name and unique label
 | 
			
		||||
// value pair establishes a new dimension and point within that dimension. Order
 | 
			
		||||
// matters, i.e. [a=1 b=2] identifies a different timeseries than [b=2 a=1].
 | 
			
		||||
type Space struct {
 | 
			
		||||
	mtx   sync.RWMutex
 | 
			
		||||
	nodes map[string]*node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Observe locates the time series identified by the name and label values in
 | 
			
		||||
// the vector space, and appends the value to the list of observations.
 | 
			
		||||
func (s *Space) Observe(name string, lvs LabelValues, value float64) {
 | 
			
		||||
	s.nodeFor(name).observe(lvs, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add locates the time series identified by the name and label values in
 | 
			
		||||
// the vector space, and appends the delta to the last value in the list of
 | 
			
		||||
// observations.
 | 
			
		||||
func (s *Space) Add(name string, lvs LabelValues, delta float64) {
 | 
			
		||||
	s.nodeFor(name).add(lvs, delta)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Walk traverses the vector space and invokes fn for each non-empty time series
 | 
			
		||||
// which is encountered. Return false to abort the traversal.
 | 
			
		||||
func (s *Space) Walk(fn func(name string, lvs LabelValues, observations []float64) bool) {
 | 
			
		||||
	s.mtx.RLock()
 | 
			
		||||
	defer s.mtx.RUnlock()
 | 
			
		||||
	for name, node := range s.nodes {
 | 
			
		||||
		f := func(lvs LabelValues, observations []float64) bool { return fn(name, lvs, observations) }
 | 
			
		||||
		if !node.walk(LabelValues{}, f) {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reset empties the current space and returns a new Space with the old
 | 
			
		||||
// contents. Reset a Space to get an immutable copy suitable for walking.
 | 
			
		||||
func (s *Space) Reset() *Space {
 | 
			
		||||
	s.mtx.Lock()
 | 
			
		||||
	defer s.mtx.Unlock()
 | 
			
		||||
	n := NewSpace()
 | 
			
		||||
	n.nodes, s.nodes = s.nodes, n.nodes
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Space) nodeFor(name string) *node {
 | 
			
		||||
	s.mtx.Lock()
 | 
			
		||||
	defer s.mtx.Unlock()
 | 
			
		||||
	if s.nodes == nil {
 | 
			
		||||
		s.nodes = map[string]*node{}
 | 
			
		||||
	}
 | 
			
		||||
	n, ok := s.nodes[name]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		n = &node{}
 | 
			
		||||
		s.nodes[name] = n
 | 
			
		||||
	}
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// node exists at a specific point in the N-dimensional vector space of all
 | 
			
		||||
// possible label values. The node collects observations and has child nodes
 | 
			
		||||
// with greater specificity.
 | 
			
		||||
type node struct {
 | 
			
		||||
	mtx          sync.RWMutex
 | 
			
		||||
	observations []float64
 | 
			
		||||
	children     map[pair]*node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type pair struct{ label, value string }
 | 
			
		||||
 | 
			
		||||
func (n *node) observe(lvs LabelValues, value float64) {
 | 
			
		||||
	n.mtx.Lock()
 | 
			
		||||
	defer n.mtx.Unlock()
 | 
			
		||||
	if len(lvs) == 0 {
 | 
			
		||||
		n.observations = append(n.observations, value)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if len(lvs) < 2 {
 | 
			
		||||
		panic("too few LabelValues; programmer error!")
 | 
			
		||||
	}
 | 
			
		||||
	head, tail := pair{lvs[0], lvs[1]}, lvs[2:]
 | 
			
		||||
	if n.children == nil {
 | 
			
		||||
		n.children = map[pair]*node{}
 | 
			
		||||
	}
 | 
			
		||||
	child, ok := n.children[head]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		child = &node{}
 | 
			
		||||
		n.children[head] = child
 | 
			
		||||
	}
 | 
			
		||||
	child.observe(tail, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *node) add(lvs LabelValues, delta float64) {
 | 
			
		||||
	n.mtx.Lock()
 | 
			
		||||
	defer n.mtx.Unlock()
 | 
			
		||||
	if len(lvs) == 0 {
 | 
			
		||||
		var value float64
 | 
			
		||||
		if len(n.observations) > 0 {
 | 
			
		||||
			value = last(n.observations) + delta
 | 
			
		||||
		} else {
 | 
			
		||||
			value = delta
 | 
			
		||||
		}
 | 
			
		||||
		n.observations = append(n.observations, value)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if len(lvs) < 2 {
 | 
			
		||||
		panic("too few LabelValues; programmer error!")
 | 
			
		||||
	}
 | 
			
		||||
	head, tail := pair{lvs[0], lvs[1]}, lvs[2:]
 | 
			
		||||
	if n.children == nil {
 | 
			
		||||
		n.children = map[pair]*node{}
 | 
			
		||||
	}
 | 
			
		||||
	child, ok := n.children[head]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		child = &node{}
 | 
			
		||||
		n.children[head] = child
 | 
			
		||||
	}
 | 
			
		||||
	child.add(tail, delta)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (n *node) walk(lvs LabelValues, fn func(LabelValues, []float64) bool) bool {
 | 
			
		||||
	n.mtx.RLock()
 | 
			
		||||
	defer n.mtx.RUnlock()
 | 
			
		||||
	if len(n.observations) > 0 && !fn(lvs, n.observations) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for p, child := range n.children {
 | 
			
		||||
		if !child.walk(append(lvs, p.label, p.value), fn) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func last(a []float64) float64 {
 | 
			
		||||
	return a[len(a)-1]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/space_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								vendor/github.com/go-kit/kit/metrics/internal/lv/space_test.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
package lv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestSpaceWalkAbort(t *testing.T) {
 | 
			
		||||
	s := NewSpace()
 | 
			
		||||
	s.Observe("a", LabelValues{"a", "b"}, 1)
 | 
			
		||||
	s.Observe("a", LabelValues{"c", "d"}, 2)
 | 
			
		||||
	s.Observe("a", LabelValues{"e", "f"}, 4)
 | 
			
		||||
	s.Observe("a", LabelValues{"g", "h"}, 8)
 | 
			
		||||
	s.Observe("b", LabelValues{"a", "b"}, 16)
 | 
			
		||||
	s.Observe("b", LabelValues{"c", "d"}, 32)
 | 
			
		||||
	s.Observe("b", LabelValues{"e", "f"}, 64)
 | 
			
		||||
	s.Observe("b", LabelValues{"g", "h"}, 128)
 | 
			
		||||
 | 
			
		||||
	var count int
 | 
			
		||||
	s.Walk(func(name string, lvs LabelValues, obs []float64) bool {
 | 
			
		||||
		count++
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
	if want, have := 1, count; want != have {
 | 
			
		||||
		t.Errorf("want %d, have %d", want, have)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSpaceWalkSums(t *testing.T) {
 | 
			
		||||
	s := NewSpace()
 | 
			
		||||
	s.Observe("metric_one", LabelValues{}, 1)
 | 
			
		||||
	s.Observe("metric_one", LabelValues{}, 2)
 | 
			
		||||
	s.Observe("metric_one", LabelValues{"a", "1", "b", "2"}, 4)
 | 
			
		||||
	s.Observe("metric_one", LabelValues{"a", "1", "b", "2"}, 8)
 | 
			
		||||
	s.Observe("metric_one", LabelValues{}, 16)
 | 
			
		||||
	s.Observe("metric_one", LabelValues{"a", "1", "b", "3"}, 32)
 | 
			
		||||
	s.Observe("metric_two", LabelValues{}, 64)
 | 
			
		||||
	s.Observe("metric_two", LabelValues{}, 128)
 | 
			
		||||
	s.Observe("metric_two", LabelValues{"a", "1", "b", "2"}, 256)
 | 
			
		||||
 | 
			
		||||
	have := map[string]float64{}
 | 
			
		||||
	s.Walk(func(name string, lvs LabelValues, obs []float64) bool {
 | 
			
		||||
		//t.Logf("%s %v => %v", name, lvs, obs)
 | 
			
		||||
		have[name+" ["+strings.Join(lvs, "")+"]"] += sum(obs)
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	want := map[string]float64{
 | 
			
		||||
		"metric_one []":     1 + 2 + 16,
 | 
			
		||||
		"metric_one [a1b2]": 4 + 8,
 | 
			
		||||
		"metric_one [a1b3]": 32,
 | 
			
		||||
		"metric_two []":     64 + 128,
 | 
			
		||||
		"metric_two [a1b2]": 256,
 | 
			
		||||
	}
 | 
			
		||||
	for keystr, wantsum := range want {
 | 
			
		||||
		if havesum := have[keystr]; wantsum != havesum {
 | 
			
		||||
			t.Errorf("%q: want %.1f, have %.1f", keystr, wantsum, havesum)
 | 
			
		||||
		}
 | 
			
		||||
		delete(want, keystr)
 | 
			
		||||
		delete(have, keystr)
 | 
			
		||||
	}
 | 
			
		||||
	for keystr, havesum := range have {
 | 
			
		||||
		t.Errorf("%q: unexpected observations recorded: %.1f", keystr, havesum)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestSpaceWalkSkipsEmptyDimensions(t *testing.T) {
 | 
			
		||||
	s := NewSpace()
 | 
			
		||||
	s.Observe("foo", LabelValues{"bar", "1", "baz", "2"}, 123)
 | 
			
		||||
 | 
			
		||||
	var count int
 | 
			
		||||
	s.Walk(func(name string, lvs LabelValues, obs []float64) bool {
 | 
			
		||||
		count++
 | 
			
		||||
		return true
 | 
			
		||||
	})
 | 
			
		||||
	if want, have := 1, count; want != have {
 | 
			
		||||
		t.Errorf("want %d, have %d", want, have)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sum(a []float64) (v float64) {
 | 
			
		||||
	for _, f := range a {
 | 
			
		||||
		v += f
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user