...
1 package zerolog
2
3 import (
4 "math/rand"
5 "sync/atomic"
6 "time"
7 )
8
9 var (
10
11 Often = RandomSampler(10)
12
13 Sometimes = RandomSampler(100)
14
15 Rarely = RandomSampler(1000)
16 )
17
18
19 type Sampler interface {
20
21
22 Sample(lvl Level) bool
23 }
24
25
26
27 type RandomSampler uint32
28
29
30 func (s RandomSampler) Sample(lvl Level) bool {
31 if s <= 0 {
32 return false
33 }
34 if rand.Intn(int(s)) != 0 {
35 return false
36 }
37 return true
38 }
39
40
41
42 type BasicSampler struct {
43 N uint32
44 counter uint32
45 }
46
47
48 func (s *BasicSampler) Sample(lvl Level) bool {
49 n := s.N
50 if n == 1 {
51 return true
52 }
53 c := atomic.AddUint32(&s.counter, 1)
54 return c%n == 1
55 }
56
57
58
59 type BurstSampler struct {
60
61
62 Burst uint32
63
64 Period time.Duration
65
66
67 NextSampler Sampler
68
69 counter uint32
70 resetAt int64
71 }
72
73
74 func (s *BurstSampler) Sample(lvl Level) bool {
75 if s.Burst > 0 && s.Period > 0 {
76 if s.inc() <= s.Burst {
77 return true
78 }
79 }
80 if s.NextSampler == nil {
81 return false
82 }
83 return s.NextSampler.Sample(lvl)
84 }
85
86 func (s *BurstSampler) inc() uint32 {
87 now := time.Now().UnixNano()
88 resetAt := atomic.LoadInt64(&s.resetAt)
89 var c uint32
90 if now > resetAt {
91 c = 1
92 atomic.StoreUint32(&s.counter, c)
93 newResetAt := now + s.Period.Nanoseconds()
94 reset := atomic.CompareAndSwapInt64(&s.resetAt, resetAt, newResetAt)
95 if !reset {
96
97 c = atomic.AddUint32(&s.counter, 1)
98 }
99 } else {
100 c = atomic.AddUint32(&s.counter, 1)
101 }
102 return c
103 }
104
105
106 type LevelSampler struct {
107 TraceSampler, DebugSampler, InfoSampler, WarnSampler, ErrorSampler Sampler
108 }
109
110 func (s LevelSampler) Sample(lvl Level) bool {
111 switch lvl {
112 case TraceLevel:
113 if s.TraceSampler != nil {
114 return s.TraceSampler.Sample(lvl)
115 }
116 case DebugLevel:
117 if s.DebugSampler != nil {
118 return s.DebugSampler.Sample(lvl)
119 }
120 case InfoLevel:
121 if s.InfoSampler != nil {
122 return s.InfoSampler.Sample(lvl)
123 }
124 case WarnLevel:
125 if s.WarnSampler != nil {
126 return s.WarnSampler.Sample(lvl)
127 }
128 case ErrorLevel:
129 if s.ErrorSampler != nil {
130 return s.ErrorSampler.Sample(lvl)
131 }
132 }
133 return true
134 }
135
View as plain text