func NilStatsReceiver(scope ...string) StatsReceiver {
	return &nilStatsReceiver{}
}
NilStats ignores all stats operations.
package stats
import (
	"encoding/json"
	"strings"
	"sync"
	"time"
	"github.com/rcrowley/go-metrics"
	log "github.com/sirupsen/logrus"
	"golang.org/x/net/context"
)
var Time StatsTime = DefaultStatsTime()
var StatReportIntvl time.Duration = 500 * time.Millisecond
var DefaultStartupGaugeSpikeLen time.Duration = 1 * time.Minute
var CurrentStatsReceiver StatsReceiver = NilStatsReceiver()
var NewCounter func() Counter = newMetricCounter
var NewGauge func() Gauge = newMetricGauge
var NewGaugeFloat func() GaugeFloat = newMetricGaugeFloat
var NewHistogram func() Histogram = newMetricHistogram
var NewLatency func() Latency = newLatency
type MarshalerPretty interface {
	MarshalJSONPretty() ([]byte, error)
}
type StatsRegistry interface {
	GetOrRegister(string, interface{}) interface{}
	Unregister(string)
	Each(func(string, interface{}))
}
type StatsReceiver interface {
	Scope(scope ...string) StatsReceiver
	Precision(time.Duration) StatsReceiver
	Counter(name ...string) Counter
	Latency(name ...string) Latency
	Gauge(name ...string) Gauge
	GaugeFloat(name ...string) GaugeFloat
	Histogram(name ...string) Histogram
	Remove(name ...string)
	Render(pretty bool) []byte
}
func DefaultStatsReceiver() StatsReceiver {
	stat, _ := NewCustomStatsReceiver(nil, 0)
	return stat
}
func NewLatchedStatsReceiver(latched time.Duration) (stat StatsReceiver, cancelFn func()) {
	return NewCustomStatsReceiver(nil, latched)
}
func NewCustomStatsReceiver(makeRegistry func() StatsRegistry, latched time.Duration) (stat StatsReceiver, cancelFn func()) {
	if makeRegistry == nil {
		makeRegistry = func() StatsRegistry { return metrics.NewRegistry() }
	}
	defaultStat := &defaultStatsReceiver{
		makeRegistry: makeRegistry,
		registry:     makeRegistry(),
		precision:    time.Millisecond,
	}
	cancel := func() {}
	if latched > 0 {
		var ctx context.Context
		defaultStat.latchCh = make(chan chan CapturedRegistry)
		ctx, cancel = context.WithCancel(context.Background())
		firstSnapshotAt := Time.Now().Add(latched).Truncate(latched)
		firstCaptured := capture(defaultStat.registry, makeRegistry())
		go latch(
			defaultStat, firstCaptured, defaultStat.latchCh,
			Time.NewTicker(latched), firstSnapshotAt, ctx)
	}
	return defaultStat, cancel
}
func latch(stat *defaultStatsReceiver, captured StatsRegistry, latchCh chan chan CapturedRegistry,
	ticker StatsTicker, firstSnapshotAt time.Time, ctx context.Context,
) {
	captureTime := Time.Now()
	for {
		select {
		case <-ctx.Done():
			ticker.Stop()
			return
		case t := <-ticker.C():
			if t.Before(firstSnapshotAt) {
				break
			}
			captured = capture(stat.registry, stat.makeRegistry())
			captureTime = t
			clear(stat.registry)
		case req := <-latchCh:
			req <- CapturedRegistry{captured, captureTime}
		}
	}
}
func capture(src StatsRegistry, captured StatsRegistry) StatsRegistry {
	src.Each(func(name string, i interface{}) {
		switch m := i.(type) {
		case Counter:
			captured.GetOrRegister(name, m.Capture())
		case Gauge:
			captured.GetOrRegister(name, m.Capture())
		case GaugeFloat:
			captured.GetOrRegister(name, m.Capture())
		case Histogram:
			captured.GetOrRegister(name, m.Capture())
		case Latency:
			captured.GetOrRegister(name, m.Capture())
		default:
			log.Info("Unrecognized capture instrument: ", name, i)
		}
	})
	return captured
}
func requestCapture(latchCh chan chan CapturedRegistry) CapturedRegistry {
	resultCh := make(chan CapturedRegistry)
	latchCh <- resultCh
	return <-resultCh
}
func clear(reg StatsRegistry) {
	reg.Each(func(name string, i interface{}) {
		switch m := i.(type) {
		case metrics.Histogram:
			m.Clear()
		}
	})
}
type CapturedRegistry struct {
	captured StatsRegistry
	time     time.Time  
}
type defaultStatsReceiver struct {
	makeRegistry func() StatsRegistry
	registry     StatsRegistry
	latchCh      chan chan CapturedRegistry
	precision    time.Duration
	scope        []string
}
func (s *defaultStatsReceiver) Scope(scope ...string) StatsReceiver {
	return &defaultStatsReceiver{s.makeRegistry, s.registry, s.latchCh, s.precision, s.scoped(scope...)}
}
func (s *defaultStatsReceiver) Precision(precision time.Duration) StatsReceiver {
	if precision < 1 {
		precision = 1
	}
	return &defaultStatsReceiver{s.makeRegistry, s.registry, s.latchCh, precision, s.scope}
}
func (s *defaultStatsReceiver) Counter(name ...string) Counter {
	return s.registry.GetOrRegister(s.scopedName(name...), NewCounter).(Counter)
}
func (s *defaultStatsReceiver) Gauge(name ...string) Gauge {
	return s.registry.GetOrRegister(s.scopedName(name...), NewGauge).(Gauge)
}
func (s *defaultStatsReceiver) GaugeFloat(name ...string) GaugeFloat {
	return s.registry.GetOrRegister(s.scopedName(name...), NewGaugeFloat).(GaugeFloat)
}
func (s *defaultStatsReceiver) Histogram(name ...string) Histogram {
	return s.registry.GetOrRegister(s.scopedName(name...), NewHistogram).(Histogram)
}
func (s *defaultStatsReceiver) Latency(name ...string) Latency {
	return s.registry.GetOrRegister(s.scopedName(name...), NewLatency().Precision(s.precision)).(Latency)
}
func (s *defaultStatsReceiver) Remove(name ...string) {
	s.registry.Unregister(s.scopedName(name...))
}
func (s *defaultStatsReceiver) render(pretty bool) []byte {
	reg := s.registry
	if s.latchCh != nil {
		reg = requestCapture(s.latchCh).captured
	}
	var err error
	var bytes []byte
	if mp, ok := reg.(MarshalerPretty); ok && pretty {
		bytes, err = mp.MarshalJSONPretty()
	} else {
		bytes, err = json.Marshal(reg)
	}
	if err != nil {
		panic("StatsRegistry bug, cannot be marshaled")
	}
	return bytes
}
func (s *defaultStatsReceiver) Render(pretty bool) []byte {
	stats := s.render(pretty)
	if s.latchCh == nil {
		clear(s.registry)  
	}
	return stats
}
func (s *defaultStatsReceiver) scoped(scope ...string) []string {
	for i, s := range scope {
		scope[i] = strings.Replace(s, "/", "_SLASH_", -1)
	}
	return append(s.scope[:], scope...)
}
func (s *defaultStatsReceiver) scopedName(scope ...string) string {
	return strings.Join(s.scoped(scope...), "/")
}