Skip to content

Commit

Permalink
Merge pull request #208 from heroku/vmc-update-testmetrics
Browse files Browse the repository at this point in the history
Update newHistogram of testmetrics Provider
  • Loading branch information
Vamsi-Mundra committed May 9, 2024
2 parents 4aec059 + 35653eb commit fbe90c5
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
35 changes: 35 additions & 0 deletions go-kit/metrics/testmetrics/metrics.go
Expand Up @@ -3,7 +3,11 @@ package testmetrics
import (
"sync"

hll "github.com/axiomhq/hyperloglog"

"github.com/go-kit/kit/metrics"

xmetrics "github.com/heroku/x/go-kit/metrics"
)

// Counter accumulates a value based on Add calls.
Expand Down Expand Up @@ -99,3 +103,34 @@ func (h *Histogram) With(labelValues ...string) metrics.Histogram {
lvs := append(append([]string(nil), h.labelValues...), labelValues...)
return h.p.newHistogram(h.name, lvs...)
}

// CardinalityCounter provides a wrapper around a HyperLogLog probabalistic
// counter. It implements CardinalityCounter Interface.
type CardinalityCounter struct {
Name string
lvs []string
mu sync.Mutex
counter *hll.Sketch
p *Provider
sync.RWMutex
}

// With implements xmetrics.CardinalityCounter interface. It returns a CardinalityCounter based on the labelValues.
func (c *CardinalityCounter) With(labelValues ...string) xmetrics.CardinalityCounter {
lvs := append(append([]string(nil), c.lvs...), labelValues...)
return c.p.newCardinalityCounter(c.Name, lvs...)
}

// Insert adds the item to the set to be counted.
func (c *CardinalityCounter) Insert(i []byte) {
c.mu.Lock()
defer c.mu.Unlock()
c.counter.Insert(i)
}

func (c *CardinalityCounter) Estimate() uint64 {
c.mu.Lock()
defer c.mu.Unlock()

return c.counter.Estimate()
}
32 changes: 22 additions & 10 deletions go-kit/metrics/testmetrics/provider.go
Expand Up @@ -10,6 +10,8 @@ import (
"sync"
"testing"

hll "github.com/axiomhq/hyperloglog"

"github.com/go-kit/kit/metrics"

xmetrics "github.com/heroku/x/go-kit/metrics"
Expand All @@ -23,7 +25,7 @@ type Provider struct {
counters map[string]*Counter
gauges map[string]*Gauge
histograms map[string]*Histogram
cardCounters map[string]*xmetrics.HLLCounter
cardCounters map[string]*CardinalityCounter
stopped bool
}

Expand All @@ -34,7 +36,7 @@ func NewProvider(t *testing.T) *Provider {
counters: make(map[string]*Counter),
histograms: make(map[string]*Histogram),
gauges: make(map[string]*Gauge),
cardCounters: make(map[string]*xmetrics.HLLCounter),
cardCounters: make(map[string]*CardinalityCounter),
}
}

Expand Down Expand Up @@ -94,20 +96,25 @@ func (p *Provider) newHistogram(name string, labelValues ...string) metrics.Hist

k := p.keyFor(name, labelValues...)
if _, ok := p.histograms[k]; !ok {
p.histograms[k] = &Histogram{name: name, p: p, labelValues: labelValues}
p.histograms[k] = &Histogram{name: name, p: p, labelValues: labelValues, observations: []float64{}}
}
return p.histograms[k]
}

// NewCardinalityCounter implements metrics.Provider.
func (p *Provider) NewCardinalityCounter(name string) xmetrics.CardinalityCounter {
return p.newCardinalityCounter(name)
}

func (p *Provider) newCardinalityCounter(name string, labelValues ...string) xmetrics.CardinalityCounter {
p.Lock()
defer p.Unlock()

if _, ok := p.cardCounters[name]; !ok {
p.cardCounters[name] = xmetrics.NewHLLCounter(name)
k := p.keyFor(name, labelValues...)
if _, ok := p.cardCounters[k]; !ok {
p.cardCounters[k] = &CardinalityCounter{Name: name, p: p, lvs: labelValues, counter: hll.New()}
}
return p.cardCounters[name]
return p.cardCounters[k]
}

// CheckCounter checks that there is a registered counter
Expand Down Expand Up @@ -308,25 +315,30 @@ func (p *Provider) CheckStopped() {

// CheckCardinalityCounter checks that there is a registered cardinality
// counter with the name and estimate provided.
func (p *Provider) CheckCardinalityCounter(name string, estimate uint64) {
func (p *Provider) CheckCardinalityCounter(name string, estimate uint64, labelValues ...string) {
p.t.Helper()

p.Lock()
defer p.Unlock()

cc, ok := p.cardCounters[name]
k := p.keyFor(name, labelValues...)
cc, ok := p.cardCounters[k]
if !ok {
keys := make([]string, 0, len(p.cardCounters))
for k := range p.cardCounters {
keys = append(keys, k)
}
available := strings.Join(keys, "\n")
p.t.Fatalf("no cardinality counter named %s out of available cardinality counter: \n%s", name, available)
p.t.Fatalf("no counter named %s out of available cardinality counters: \n%s", k, available)
}
actualEstimate := cc.Estimate()
if actualEstimate != estimate {
if estimate != actualEstimate {
p.t.Fatalf("%v = %v, want %v", name, actualEstimate, estimate)
}

if len(labelValues) > 0 && !reflect.DeepEqual(labelValues, cc.lvs) {
p.t.Fatalf("want counter label values: %#v, got %#v", labelValues, cc.lvs)
}
}

func (p *Provider) keyFor(name string, labelValues ...string) string {
Expand Down

0 comments on commit fbe90c5

Please sign in to comment.