Skip to content
This repository was archived by the owner on Sep 17, 2025. It is now read-only.

Commit 70fcb6c

Browse files
authored
Change sampling rule of FixedRateSampler (#48)
1 parent bece5d9 commit 70fcb6c

10 files changed

Lines changed: 73 additions & 36 deletions

File tree

trace/opencensus/trace/request_tracer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def should_sample(self):
7474
:returns: Whether to trace the request or not.
7575
"""
7676
return self.span_context.trace_options.enabled \
77-
and self.sampler.should_sample
77+
and self.sampler.should_sample(self.span_context.trace_id)
7878

7979
def get_tracer(self):
8080
"""Return a tracer according to the sampling decision."""

trace/opencensus/trace/samplers/always_off.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
class AlwaysOffSampler(Sampler):
1919

20-
@property
21-
def should_sample(self):
20+
def should_sample(self, trace_id):
2221
"""Always return False because we don't want to sample."""
2322
return False

trace/opencensus/trace/samplers/always_on.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
class AlwaysOnSampler(Sampler):
1919

20-
@property
21-
def should_sample(self):
20+
def should_sample(self, trace_id):
2221
"""Always return True because we want to sampler all requests."""
2322
return True

trace/opencensus/trace/samplers/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class Sampler(object):
2121
Subclasses of :class:`Sampler` must override :meth:`should_sample`.
2222
"""
2323

24-
@property
25-
def should_sample(self):
24+
def should_sample(self, trace_id):
2625
"""Determine whether to sample this request or not."""
2726
raise NotImplementedError

trace/opencensus/trace/samplers/fixed_rate.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,46 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import random
16-
1715
from opencensus.trace.samplers.base import Sampler
1816

1917
DEFAULT_SAMPLING_RATE = 0.5
2018

19+
MAX_VALUE = 0xffffffffffffffff
20+
2121

2222
class FixedRateSampler(Sampler):
2323
"""Sample a request at a fixed rate.
2424
2525
:type rate: float
2626
:param rate: The rate of sampling.
2727
"""
28-
def __init__(self, rate=DEFAULT_SAMPLING_RATE):
28+
def __init__(self, rate=None):
29+
if rate is None:
30+
rate = DEFAULT_SAMPLING_RATE
31+
2932
if rate > 1 or rate < 0:
3033
raise ValueError('Rate must between 0 and 1.')
3134

3235
self.rate = rate
3336

34-
@property
35-
def should_sample(self):
36-
random_number = random.uniform(0, 1)
37+
def should_sample(self, trace_id):
38+
lower_long = get_lower_long_from_trace_id(trace_id)
39+
bound = self.rate * MAX_VALUE
3740

38-
if random_number <= self.rate:
41+
if lower_long <= bound:
3942
return True
4043
else:
4144
return False
45+
46+
47+
def get_lower_long_from_trace_id(trace_id):
48+
"""Returns the lower 8 bytes of the trace ID as a long value, assuming
49+
little endian order.
50+
51+
:rtype: long
52+
:returns: Lower 8 bytes of trace ID
53+
"""
54+
lower_bytes = trace_id[16:]
55+
lower_long = int(lower_bytes, 16)
56+
57+
return lower_long

trace/tests/unit/samplers/test_always_off.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ def test_should_sample(self):
2020
from opencensus.trace.samplers import always_off
2121

2222
sampler = always_off.AlwaysOffSampler()
23-
should_sample = sampler.should_sample
23+
should_sample = sampler.should_sample(trace_id='fake_id')
2424

2525
self.assertFalse(should_sample)

trace/tests/unit/samplers/test_always_on.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ def test_should_sample(self):
2020
from opencensus.trace.samplers import always_on
2121

2222
sampler = always_on.AlwaysOnSampler()
23-
should_sample = sampler.should_sample
23+
should_sample = sampler.should_sample(trace_id='fake_id')
2424

2525
self.assertTrue(should_sample)

trace/tests/unit/samplers/test_base_sampler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ def test_should_sample_abstract(self):
2222
sampler = base.Sampler()
2323

2424
with self.assertRaises(NotImplementedError):
25-
sampler.should_sample()
25+
sampler.should_sample(trace_id='fake_id')

trace/tests/unit/samplers/test_fixed_rate.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,43 @@ def test_constructor_invalid(self):
2424
fixed_rate.FixedRateSampler(rate=2)
2525

2626
def test_constructor_valid(self):
27-
rate = 0.5
27+
rate = 0.8
28+
trace_id = 'f8739df974a4481f98748cd92b27177d'
2829
sampler = fixed_rate.FixedRateSampler(rate=rate)
2930

3031
self.assertEqual(sampler.rate, rate)
3132

33+
def test_constructor_default(self):
34+
rate = 0.5
35+
trace_id = 'f8739df974a4481f98748cd92b27177d'
36+
sampler = fixed_rate.FixedRateSampler()
37+
38+
self.assertEqual(sampler.rate, rate)
39+
3240
def test_should_sample_smaller(self):
41+
trace_id = 'f8739df974a4481f98748cd92b27177d'
3342
sampler = fixed_rate.FixedRateSampler(rate=1)
34-
should_sample = sampler.should_sample
43+
should_sample = sampler.should_sample(trace_id=trace_id)
3544

3645
self.assertTrue(should_sample)
3746

3847
def test_should_sample_greater(self):
48+
trace_id = 'f8739df974a4481f98748cd92b27177d'
3949
sampler = fixed_rate.FixedRateSampler(rate=0)
40-
should_sample = sampler.should_sample
50+
should_sample = sampler.should_sample(trace_id=trace_id)
51+
52+
self.assertFalse(should_sample)
53+
54+
def test_should_sample_trace_id_sampled(self):
55+
trace_id = '00000000000000000000000000000000'
56+
sampler = fixed_rate.FixedRateSampler(rate=0.5)
57+
should_sample = sampler.should_sample(trace_id=trace_id)
58+
59+
self.assertTrue(should_sample)
60+
61+
def test_should_sample_trace_id_not_sampled(self):
62+
trace_id = 'ffffffffffffffffffffffffffffffff'
63+
sampler = fixed_rate.FixedRateSampler(rate=0.5)
64+
should_sample = sampler.should_sample(trace_id=trace_id)
4165

4266
self.assertFalse(should_sample)

trace/tests/unit/test_request_tracer.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def test_constructor_explicit(self):
4242
from opencensus.trace.tracer import noop_tracer
4343

4444
sampler = mock.Mock()
45-
sampler.should_sample = False
45+
sampler.should_sample.return_value = False
4646

4747
exporter = mock.Mock()
4848
propagator = mock.Mock()
@@ -73,15 +73,15 @@ def test_should_sample_force_not_trace(self):
7373

7474
def test_should_sample_sampled(self):
7575
sampler =mock.Mock()
76-
sampler.should_sample = True
76+
sampler.should_sample.return_value = True
7777
tracer = request_tracer.RequestTracer(sampler=sampler)
7878
sampled = tracer.should_sample()
7979

8080
self.assertTrue(sampled)
8181

8282
def test_should_sample_not_sampled(self):
8383
sampler = mock.Mock()
84-
sampler.should_sample = False
84+
sampler.should_sample.return_value = False
8585
tracer = request_tracer.RequestTracer(sampler=sampler)
8686
sampled = tracer.should_sample()
8787

@@ -91,7 +91,7 @@ def get_tracer_noop_tracer(self):
9191
from opencensus.trace.tracer import noop_tracer
9292

9393
sampler = mock.Mock()
94-
sampler.should_sample = False
94+
sampler.should_sample.return_value = False
9595
tracer = request_tracer.RequestTracer(sampler=sampler)
9696

9797
result = tracer.get_tracer()
@@ -102,7 +102,7 @@ def get_tracer_context_tracer(self):
102102
from opencensus.trace.tracer import context_tracer
103103

104104
sampler = mock.Mock()
105-
sampler.should_sample = True
105+
sampler.should_sample.return_value = True
106106
tracer = request_tracer.RequestTracer(sampler=sampler)
107107

108108
result = tracer.get_tracer()
@@ -113,7 +113,7 @@ def test_finish_not_sampled(self):
113113
from opencensus.trace.tracer import noop_tracer
114114

115115
sampler = mock.Mock()
116-
sampler.should_sample = False
116+
sampler.should_sample.return_value = False
117117
tracer = request_tracer.RequestTracer(sampler=sampler)
118118
assert isinstance(tracer.tracer, noop_tracer.NoopTracer)
119119
mock_tracer = mock.Mock()
@@ -125,7 +125,7 @@ def test_finish_sampled(self):
125125
from opencensus.trace.tracer import context_tracer
126126

127127
sampler = mock.Mock()
128-
sampler.should_sample = True
128+
sampler.should_sample.return_value = True
129129
tracer = request_tracer.RequestTracer(sampler=sampler)
130130
assert isinstance(tracer.tracer, context_tracer.ContextTracer)
131131
mock_tracer = mock.Mock()
@@ -137,15 +137,15 @@ def test_span_not_sampled(self):
137137
from opencensus.trace.tracer import base
138138

139139
sampler = mock.Mock()
140-
sampler.should_sample = False
140+
sampler.should_sample.return_value = False
141141
tracer = request_tracer.RequestTracer(sampler=sampler)
142142

143143
span = tracer.span()
144144
assert isinstance(span, base.NullContextManager)
145145

146146
def test_span_sampled(self):
147147
sampler = mock.Mock()
148-
sampler.should_sample = True
148+
sampler.should_sample.return_value = True
149149
tracer = request_tracer.RequestTracer(sampler=sampler)
150150
tracer_mock = mock.Mock()
151151
tracer.tracer = tracer_mock
@@ -158,7 +158,7 @@ def test_start_span_not_sampled(self):
158158
from opencensus.trace.tracer import base
159159

160160
sampler = mock.Mock()
161-
sampler.should_sample = False
161+
sampler.should_sample.return_value = False
162162
tracer = request_tracer.RequestTracer(sampler=sampler)
163163

164164
span = tracer.start_span()
@@ -169,15 +169,15 @@ def test_start_span_sampled(self):
169169
from opencensus.trace import span as trace_span
170170

171171
sampler = mock.Mock()
172-
sampler.should_sample = True
172+
sampler.should_sample.return_value = True
173173
tracer = request_tracer.RequestTracer(sampler=sampler)
174174
span = tracer.start_span()
175175

176176
assert isinstance(span, trace_span.Span)
177177

178178
def test_end_span_not_sampled(self):
179179
sampler = mock.Mock()
180-
sampler.should_sample = False
180+
sampler.should_sample.return_value = False
181181
span_context = mock.Mock()
182182
tracer = request_tracer.RequestTracer(
183183
sampler=sampler,
@@ -189,7 +189,7 @@ def test_end_span_not_sampled(self):
189189

190190
def test_end_span_sampled(self):
191191
sampler = mock.Mock()
192-
sampler.should_sample = True
192+
sampler.should_sample.return_value = True
193193
tracer = request_tracer.RequestTracer(sampler=sampler)
194194
span = mock.Mock()
195195
tracer.tracer._span_stack.append(span)
@@ -201,7 +201,7 @@ def test_current_span_not_sampled(self):
201201
from opencensus.trace.tracer import base
202202

203203
sampler = mock.Mock()
204-
sampler.should_sample = False
204+
sampler.should_sample.return_value = False
205205
tracer = request_tracer.RequestTracer(sampler=sampler)
206206

207207
span = tracer.current_span()
@@ -210,7 +210,7 @@ def test_current_span_not_sampled(self):
210210

211211
def test_current_span_sampled(self):
212212
sampler = mock.Mock()
213-
sampler.should_sample = True
213+
sampler.should_sample.return_value = True
214214
tracer = request_tracer.RequestTracer(sampler=sampler)
215215
span = mock.Mock()
216216
tracer.tracer._span_stack.append(span)
@@ -223,7 +223,7 @@ def test_add_label_to_current_span_not_sampled(self):
223223
from opencensus.trace.tracer import base
224224

225225
sampler = mock.Mock()
226-
sampler.should_sample = False
226+
sampler.should_sample.return_value = False
227227
tracer = request_tracer.RequestTracer(sampler=sampler)
228228
tracer.add_label_to_current_span('key', 'value')
229229

0 commit comments

Comments
 (0)