summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/rs/zerolog/sampler.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/rs/zerolog/sampler.go')
-rw-r--r--vendor/github.com/rs/zerolog/sampler.go134
1 files changed, 134 insertions, 0 deletions
diff --git a/vendor/github.com/rs/zerolog/sampler.go b/vendor/github.com/rs/zerolog/sampler.go
new file mode 100644
index 00000000..1be98c4f
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/sampler.go
@@ -0,0 +1,134 @@
+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
+}