func (mc *CountersWithMultiLabels) Reset(names []string) {
	if len(names) != len(mc.labels) {
		panic("CountersWithMultiLabels: wrong number of values in Reset")
	}
	mc.counters.Reset(safeJoinLabels(names))
}
Reset resets the value of a named counter back to 0.
len(names) must be equal to len(Labels).
package stats
import (
	"bytes"
	"fmt"
	"sync"
	"sync/atomic"
	"github.com/nooncall/shazam/log"
)
type counters struct {
	mu     sync.RWMutex
	counts map[string]*int64
	help   string
}
func (c *counters) String() string {
	b := bytes.NewBuffer(make([]byte, 0, 4096))
	c.mu.RLock()
	defer c.mu.RUnlock()
	fmt.Fprintf(b, "{")
	firstValue := true
	for k, a := range c.counts {
		if firstValue {
			firstValue = false
		} else {
			fmt.Fprintf(b, ", ")
		}
		fmt.Fprintf(b, "%q: %v", k, atomic.LoadInt64(a))
	}
	fmt.Fprintf(b, "}")
	return b.String()
}
func (c *counters) getValueAddr(name string) *int64 {
	c.mu.RLock()
	a, ok := c.counts[name]
	c.mu.RUnlock()
	if ok {
		return a
	}
	c.mu.Lock()
	defer c.mu.Unlock()
	a, ok = c.counts[name]
	if ok {
		return a
	}
	a = new(int64)
	c.counts[name] = a
	return a
}
func (c *counters) Add(name string, value int64) {
	a := c.getValueAddr(name)
	atomic.AddInt64(a, value)
}
func (c *counters) ResetAll() {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.counts = make(map[string]*int64)
}
func (c *counters) ZeroAll() {
	c.mu.Lock()
	defer c.mu.Unlock()
	for _, a := range c.counts {
		atomic.StoreInt64(a, int64(0))
	}
}
func (c *counters) Reset(name string) {
	a := c.getValueAddr(name)
	atomic.StoreInt64(a, int64(0))
}
func (c *counters) Counts() map[string]int64 {
	c.mu.RLock()
	defer c.mu.RUnlock()
	counts := make(map[string]int64, len(c.counts))
	for k, a := range c.counts {
		counts[k] = atomic.LoadInt64(a)
	}
	return counts
}
func (c *counters) Help() string {
	return c.help
}
type CountersWithSingleLabel struct {
	counters
	label string
}
func NewCountersWithSingleLabel(name, help, label string, tags ...string) *CountersWithSingleLabel {
	c := &CountersWithSingleLabel{
		counters: counters{
			counts: make(map[string]*int64),
			help:   help,
		},
		label: label,
	}
	for _, tag := range tags {
		c.counts[tag] = new(int64)
	}
	if name != "" {
		publish(name, c)
	}
	return c
}
func (c *CountersWithSingleLabel) Label() string {
	return c.label
}
func (c *CountersWithSingleLabel) Add(name string, value int64) {
	if value < 0 {
		log.Warn("[stats] Adding a negative value to a counter, %v should be a gauge instead", c)
	}
	a := c.getValueAddr(name)
	atomic.AddInt64(a, value)
}
type CountersWithMultiLabels struct {
	counters
	labels []string
}
func NewCountersWithMultiLabels(name, help string, labels []string) *CountersWithMultiLabels {
	t := &CountersWithMultiLabels{
		counters: counters{
			counts: make(map[string]*int64),
			help:   help},
		labels: labels,
	}
	if name != "" {
		publish(name, t)
	}
	return t
}
func (mc *CountersWithMultiLabels) Labels() []string {
	return mc.labels
}
func (mc *CountersWithMultiLabels) Add(names []string, value int64) {
	if len(names) != len(mc.labels) {
		panic("CountersWithMultiLabels: wrong number of values in Add")
	}
	if value < 0 {
		log.Warn("[stats] Adding a negative value to a counter, %v should be a gauge instead", mc)
	}
	mc.counters.Add(safeJoinLabels(names), value)
}