func NewSamplerWithOptions(core Core, tick time.Duration, first, thereafter int, opts ...SamplerOption) Core {
	s := &sampler{
		Core:       core,
		tick:       tick,
		counts:     newCounters(),
		first:      uint64(first),
		thereafter: uint64(thereafter),
		hook:       nopSamplingHook,
	}
	for _, opt := range opts {
		opt.apply(s)
	}
	return s
}
NewSamplerWithOptions creates a Core that samples incoming entries, which
caps the CPU and I/O load of logging while attempting to preserve a
representative subset of your logs.

Zap samples by logging the first N entries with a given level and message
each tick. If more Entries with the same level and message are seen during
the same interval, every Mth message is logged and the rest are dropped.

Sampler can be configured to report sampling decisions with the SamplerHook
option.

Keep in mind that zap's sampling implementation is optimized for speed over
absolute precision; under load, each tick may be slightly over- or
under-sampled.
package zapcore
import (
	"time"
	"go.uber.org/atomic"
)
const (
	_numLevels        = _maxLevel - _minLevel + 1
	_countersPerLevel = 4096
)
type counter struct {
	resetAt atomic.Int64
	counter atomic.Uint64
}
type counters [_numLevels][_countersPerLevel]counter
func newCounters() *counters {
	return &counters{}
}
func (cs *counters) get(lvl Level, key string) *counter {
	i := lvl - _minLevel
	j := fnv32a(key) % _countersPerLevel
	return &cs[i][j]
}
func fnv32a(s string) uint32 {
	const (
		offset32 = 2166136261
		prime32  = 16777619
	)
	hash := uint32(offset32)
	for i := 0; i < len(s); i++ {
		hash ^= uint32(s[i])
		hash *= prime32
	}
	return hash
}
func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 {
	tn := t.UnixNano()
	resetAfter := c.resetAt.Load()
	if resetAfter > tn {
		return c.counter.Inc()
	}
	c.counter.Store(1)
	newResetAfter := tn + tick.Nanoseconds()
	if !c.resetAt.CAS(resetAfter, newResetAfter) {
		return c.counter.Inc()
	}
	return 1
}
type SamplingDecision uint32
const (
	LogDropped SamplingDecision = 1 << iota
	LogSampled
)
type optionFunc func(*sampler)
func (f optionFunc) apply(s *sampler) {
	f(s)
}
type SamplerOption interface {
	apply(*sampler)
}
func nopSamplingHook(Entry, SamplingDecision) {}
func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption {
	return optionFunc(func(s *sampler) {
		s.hook = hook
	})
}