func (g *Gauge) Snapshot() int64 {
	return atomic.LoadInt64(&g.value)
}
Snapshot returns the current value.
package instruments
import (
	"math/rand"
	"sync"
	"sync/atomic"
	"time"
)
const rateScale = 1e-9
type Discrete interface {
	Snapshot() int64
}
type Sample interface {
	Snapshot() []int64
}
func Scale(o, d time.Duration) float64 {
	return float64(o) / float64(d)
}
type Counter struct {
	count int64
}
func NewCounter() *Counter {
	return new(Counter)
}
func (c *Counter) Update(v int64) {
	atomic.AddInt64(&c.count, v)
}
func (c *Counter) Snapshot() int64 {
	return atomic.SwapInt64(&c.count, 0)
}
type Rate struct {
	time  int64
	unit  time.Duration
	count *Counter
	m     sync.Mutex
}
func NewRate() *Rate {
	return NewRateScale(time.Second)
}
func NewRateScale(d time.Duration) *Rate {
	return &Rate{
		time:  time.Now().UnixNano(),
		unit:  d,
		count: NewCounter(),
	}
}
func (r *Rate) Update(v int64) {
	r.count.Update(v)
}
func (r *Rate) Snapshot() int64 {
	r.m.Lock()
	defer r.m.Unlock()
	now := time.Now().UnixNano()
	t := atomic.SwapInt64(&r.time, now)
	c := r.count.Snapshot()
	s := float64(c) / rateScale / float64(now-t)
	return Ceil(s * Scale(r.unit, time.Second))
}
type Derive struct {
	rate  *Rate
	value int64
}
func NewDerive(v int64) *Derive {
	return &Derive{
		value: v,
		rate:  NewRate(),
	}
}
func NewDeriveScale(v int64, d time.Duration) *Derive {
	return &Derive{
		value: v,
		rate:  NewRateScale(d),
	}
}
func (d *Derive) Update(v int64) {
	p := atomic.SwapInt64(&d.value, v)
	d.rate.Update(v - p)
}
func (d *Derive) Snapshot() int64 {
	return d.rate.Snapshot()
}
type Reservoir struct {
	size   int64
	values []int64
	m      sync.Mutex
}
const defaultReservoirSize = 1028
func NewReservoir(size int64) *Reservoir {
	if size <= 0 {
		size = defaultReservoirSize
	}
	return &Reservoir{
		values: make([]int64, size),
	}
}
func (r *Reservoir) Update(v int64) {
	r.m.Lock()
	defer r.m.Unlock()
	s := atomic.AddInt64(&r.size, 1)
	if int(s) <= len(r.values) {
		r.values[s-1] = v
	} else {
		l := rand.Int63n(s)
		if int(l) < len(r.values) {
			r.values[l] = v
		}
	}
}
func (r *Reservoir) Snapshot() []int64 {
	r.m.Lock()
	defer r.m.Unlock()
	s := atomic.SwapInt64(&r.size, 0)
	v := make([]int64, min(int(s), len(r.values)))
	copy(v, r.values)
	r.values = make([]int64, cap(r.values))
	sorted(v)
	return v
}
type Gauge struct {
	value int64
}
func NewGauge(v int64) *Gauge {
	return &Gauge{
		value: v,
	}
}
func (g *Gauge) Update(v int64) {
	atomic.StoreInt64(&g.value, v)
}