stash/vendor/github.com/rs/zerolog/sampler.go
SmallCoccinelle 45f700d6ea
Support Go 1.18: Upgrade gqlgen to v0.17.2 (#2443)
* Upgrade gqlgen to v0.17.2

This enables builds on Go 1.18. github.com/vektah/gqlparser is upgraded
to the newest version too.

Getting this to work is a bit of a hazzle. I had to first remove
vendoring from the repository, perform the upgrade and then re-introduce
the vendor directory. I think gqlgens analysis went wrong for some
reason on the upgrade. It would seem a clean-room installation fixed it.

* Bump project to 1.18

* Update all packages, address gqlgenc breaking changes

* Let `go mod tidy` handle the go.mod file

* Upgrade linter to 1.45.2

* Introduce v1.45.2 of the linter

The linter now correctly warns on `strings.Title` because it isn't
unicode-aware. Fix this by using the suggested fix from x/text/cases
to produce unicode-aware strings.

The mapping isn't entirely 1-1 as this new approach has a larger iface:
it spans all of unicode rather than just ASCII. It coincides for ASCII
however, so things should be largely the same.

* Ready ourselves for errchkjson and contextcheck.

* Revert dockerfile golang version changes for now

Co-authored-by: Kermie <kermie@isinthe.house>
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
2022-04-02 18:08:14 +11:00

134 lines
3.1 KiB
Go

package zerolog
import (
"math/rand"
"sync/atomic"
"time"
)
var (
// Often samples log every ~ 10 events.
Often = RandomSampler(10)
// Sometimes samples log every ~ 100 events.
Sometimes = RandomSampler(100)
// Rarely samples log every ~ 1000 events.
Rarely = RandomSampler(1000)
)
// Sampler defines an interface to a log sampler.
type Sampler interface {
// Sample returns true if the event should be part of the sample, false if
// the event should be dropped.
Sample(lvl Level) bool
}
// RandomSampler use a PRNG to randomly sample an event out of N events,
// regardless of their level.
type RandomSampler uint32
// Sample implements the Sampler interface.
func (s RandomSampler) Sample(lvl Level) bool {
if s <= 0 {
return false
}
if rand.Intn(int(s)) != 0 {
return false
}
return true
}
// BasicSampler is a sampler that will send every Nth events, regardless of
// their level.
type BasicSampler struct {
N uint32
counter uint32
}
// Sample implements the Sampler interface.
func (s *BasicSampler) Sample(lvl Level) bool {
n := s.N
if n == 1 {
return true
}
c := atomic.AddUint32(&s.counter, 1)
return c%n == 1
}
// BurstSampler lets Burst events pass per Period then pass the decision to
// NextSampler. If Sampler is not set, all subsequent events are rejected.
type BurstSampler struct {
// Burst is the maximum number of event per period allowed before calling
// NextSampler.
Burst uint32
// Period defines the burst period. If 0, NextSampler is always called.
Period time.Duration
// NextSampler is the sampler used after the burst is reached. If nil,
// events are always rejected after the burst.
NextSampler Sampler
counter uint32
resetAt int64
}
// Sample implements the Sampler interface.
func (s *BurstSampler) Sample(lvl Level) bool {
if s.Burst > 0 && s.Period > 0 {
if s.inc() <= s.Burst {
return true
}
}
if s.NextSampler == nil {
return false
}
return s.NextSampler.Sample(lvl)
}
func (s *BurstSampler) inc() uint32 {
now := time.Now().UnixNano()
resetAt := atomic.LoadInt64(&s.resetAt)
var c uint32
if now > resetAt {
c = 1
atomic.StoreUint32(&s.counter, c)
newResetAt := now + s.Period.Nanoseconds()
reset := atomic.CompareAndSwapInt64(&s.resetAt, resetAt, newResetAt)
if !reset {
// Lost the race with another goroutine trying to reset.
c = atomic.AddUint32(&s.counter, 1)
}
} else {
c = atomic.AddUint32(&s.counter, 1)
}
return c
}
// LevelSampler applies a different sampler for each level.
type LevelSampler struct {
TraceSampler, DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler
}
func (s LevelSampler) Sample(lvl Level) bool {
switch lvl {
case TraceLevel:
if s.TraceSampler != nil {
return s.TraceSampler.Sample(lvl)
}
case DebugLevel:
if s.DebugSampler != nil {
return s.DebugSampler.Sample(lvl)
}
case InfoLevel:
if s.InfoSampler != nil {
return s.InfoSampler.Sample(lvl)
}
case WarnLevel:
if s.WarnSampler != nil {
return s.WarnSampler.Sample(lvl)
}
case ErrorLevel:
if s.ErrorSampler != nil {
return s.ErrorSampler.Sample(lvl)
}
}
return true
}