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
|
||||
}
|
40
vendor/github.com/go-kit/kit/metrics/internal/ratemap/ratemap.go
generated
vendored
Normal file
40
vendor/github.com/go-kit/kit/metrics/internal/ratemap/ratemap.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// Package ratemap implements a goroutine-safe map of string to float64. It can
|
||||
// be embedded in implementations whose metrics support fixed sample rates, so
|
||||
// that an additional parameter doesn't have to be tracked through the e.g.
|
||||
// lv.Space object.
|
||||
package ratemap
|
||||
|
||||
import "sync"
|
||||
|
||||
// RateMap is a simple goroutine-safe map of string to float64.
|
||||
type RateMap struct {
|
||||
mtx sync.RWMutex
|
||||
m map[string]float64
|
||||
}
|
||||
|
||||
// New returns a new RateMap.
|
||||
func New() *RateMap {
|
||||
return &RateMap{
|
||||
m: map[string]float64{},
|
||||
}
|
||||
}
|
||||
|
||||
// Set writes the given name/rate pair to the map.
|
||||
// Set is safe for concurrent access by multiple goroutines.
|
||||
func (m *RateMap) Set(name string, rate float64) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
m.m[name] = rate
|
||||
}
|
||||
|
||||
// Get retrieves the rate for the given name, or 1.0 if none is set.
|
||||
// Get is safe for concurrent access by multiple goroutines.
|
||||
func (m *RateMap) Get(name string) float64 {
|
||||
m.mtx.RLock()
|
||||
defer m.mtx.RUnlock()
|
||||
f, ok := m.m[name]
|
||||
if !ok {
|
||||
f = 1.0
|
||||
}
|
||||
return f
|
||||
}
|
Reference in New Issue
Block a user