• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.trace.samplers;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import io.opencensus.trace.NoopSpan;
22 import io.opencensus.trace.Sampler;
23 import io.opencensus.trace.Span;
24 import io.opencensus.trace.SpanContext;
25 import io.opencensus.trace.SpanId;
26 import io.opencensus.trace.TraceId;
27 import io.opencensus.trace.TraceOptions;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.EnumSet;
31 import java.util.List;
32 import java.util.Random;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 import org.junit.runners.JUnit4;
36 
37 /** Unit tests for {@link Samplers}. */
38 @RunWith(JUnit4.class)
39 public class SamplersTest {
40   private static final String SPAN_NAME = "MySpanName";
41   private static final int NUM_SAMPLE_TRIES = 1000;
42   private final Random random = new Random(1234);
43   private final TraceId traceId = TraceId.generateRandomId(random);
44   private final SpanId parentSpanId = SpanId.generateRandomId(random);
45   private final SpanId spanId = SpanId.generateRandomId(random);
46   private final SpanContext sampledSpanContext =
47       SpanContext.create(traceId, parentSpanId, TraceOptions.builder().setIsSampled(true).build());
48   private final SpanContext notSampledSpanContext =
49       SpanContext.create(traceId, parentSpanId, TraceOptions.DEFAULT);
50   private final Span sampledSpan =
51       new NoopSpan(sampledSpanContext, EnumSet.of(Span.Options.RECORD_EVENTS));
52 
53   @Test
alwaysSampleSampler_AlwaysReturnTrue()54   public void alwaysSampleSampler_AlwaysReturnTrue() {
55     // Sampled parent.
56     assertThat(
57             Samplers.alwaysSample()
58                 .shouldSample(
59                     sampledSpanContext,
60                     false,
61                     traceId,
62                     spanId,
63                     "Another name",
64                     Collections.<Span>emptyList()))
65         .isTrue();
66     // Not sampled parent.
67     assertThat(
68             Samplers.alwaysSample()
69                 .shouldSample(
70                     notSampledSpanContext,
71                     false,
72                     traceId,
73                     spanId,
74                     "Yet another name",
75                     Collections.<Span>emptyList()))
76         .isTrue();
77   }
78 
79   @Test
alwaysSampleSampler_ToString()80   public void alwaysSampleSampler_ToString() {
81     assertThat(Samplers.alwaysSample().toString()).isEqualTo("AlwaysSampleSampler");
82   }
83 
84   @Test
neverSampleSampler_AlwaysReturnFalse()85   public void neverSampleSampler_AlwaysReturnFalse() {
86     // Sampled parent.
87     assertThat(
88             Samplers.neverSample()
89                 .shouldSample(
90                     sampledSpanContext,
91                     false,
92                     traceId,
93                     spanId,
94                     "bar",
95                     Collections.<Span>emptyList()))
96         .isFalse();
97     // Not sampled parent.
98     assertThat(
99             Samplers.neverSample()
100                 .shouldSample(
101                     notSampledSpanContext,
102                     false,
103                     traceId,
104                     spanId,
105                     "quux",
106                     Collections.<Span>emptyList()))
107         .isFalse();
108   }
109 
110   @Test
neverSampleSampler_ToString()111   public void neverSampleSampler_ToString() {
112     assertThat(Samplers.neverSample().toString()).isEqualTo("NeverSampleSampler");
113   }
114 
115   @Test(expected = IllegalArgumentException.class)
probabilitySampler_outOfRangeHighProbability()116   public void probabilitySampler_outOfRangeHighProbability() {
117     Samplers.probabilitySampler(1.01);
118   }
119 
120   @Test(expected = IllegalArgumentException.class)
probabilitySampler_outOfRangeLowProbability()121   public void probabilitySampler_outOfRangeLowProbability() {
122     Samplers.probabilitySampler(-0.00001);
123   }
124 
125   // Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs.
assertSamplerSamplesWithProbability( Sampler sampler, SpanContext parent, List<Span> parentLinks, double probability)126   private static void assertSamplerSamplesWithProbability(
127       Sampler sampler, SpanContext parent, List<Span> parentLinks, double probability) {
128     Random random = new Random(1234);
129     int count = 0; // Count of spans with sampling enabled
130     for (int i = 0; i < NUM_SAMPLE_TRIES; i++) {
131       if (sampler.shouldSample(
132           parent,
133           false,
134           TraceId.generateRandomId(random),
135           SpanId.generateRandomId(random),
136           SPAN_NAME,
137           parentLinks)) {
138         count++;
139       }
140     }
141     double proportionSampled = (double) count / NUM_SAMPLE_TRIES;
142     // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness.
143     assertThat(proportionSampled < probability + 0.1 && proportionSampled > probability - 0.1)
144         .isTrue();
145   }
146 
147   @Test
probabilitySampler_DifferentProbabilities_NotSampledParent()148   public void probabilitySampler_DifferentProbabilities_NotSampledParent() {
149     final Sampler neverSample = Samplers.probabilitySampler(0.0);
150     assertSamplerSamplesWithProbability(
151         neverSample, notSampledSpanContext, Collections.<Span>emptyList(), 0.0);
152     final Sampler alwaysSample = Samplers.probabilitySampler(1.0);
153     assertSamplerSamplesWithProbability(
154         alwaysSample, notSampledSpanContext, Collections.<Span>emptyList(), 1.0);
155     final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5);
156     assertSamplerSamplesWithProbability(
157         fiftyPercentSample, notSampledSpanContext, Collections.<Span>emptyList(), 0.5);
158     final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2);
159     assertSamplerSamplesWithProbability(
160         twentyPercentSample, notSampledSpanContext, Collections.<Span>emptyList(), 0.2);
161     final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0);
162     assertSamplerSamplesWithProbability(
163         twoThirdsSample, notSampledSpanContext, Collections.<Span>emptyList(), 2.0 / 3.0);
164   }
165 
166   @Test
probabilitySampler_DifferentProbabilities_SampledParent()167   public void probabilitySampler_DifferentProbabilities_SampledParent() {
168     final Sampler neverSample = Samplers.probabilitySampler(0.0);
169     assertSamplerSamplesWithProbability(
170         neverSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0);
171     final Sampler alwaysSample = Samplers.probabilitySampler(1.0);
172     assertSamplerSamplesWithProbability(
173         alwaysSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0);
174     final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5);
175     assertSamplerSamplesWithProbability(
176         fiftyPercentSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0);
177     final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2);
178     assertSamplerSamplesWithProbability(
179         twentyPercentSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0);
180     final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0);
181     assertSamplerSamplesWithProbability(
182         twoThirdsSample, sampledSpanContext, Collections.<Span>emptyList(), 1.0);
183   }
184 
185   @Test
probabilitySampler_DifferentProbabilities_SampledParentLink()186   public void probabilitySampler_DifferentProbabilities_SampledParentLink() {
187     final Sampler neverSample = Samplers.probabilitySampler(0.0);
188     assertSamplerSamplesWithProbability(
189         neverSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0);
190     final Sampler alwaysSample = Samplers.probabilitySampler(1.0);
191     assertSamplerSamplesWithProbability(
192         alwaysSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0);
193     final Sampler fiftyPercentSample = Samplers.probabilitySampler(0.5);
194     assertSamplerSamplesWithProbability(
195         fiftyPercentSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0);
196     final Sampler twentyPercentSample = Samplers.probabilitySampler(0.2);
197     assertSamplerSamplesWithProbability(
198         twentyPercentSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0);
199     final Sampler twoThirdsSample = Samplers.probabilitySampler(2.0 / 3.0);
200     assertSamplerSamplesWithProbability(
201         twoThirdsSample, notSampledSpanContext, Arrays.asList(sampledSpan), 1.0);
202   }
203 
204   @Test
probabilitySampler_SampleBasedOnTraceId()205   public void probabilitySampler_SampleBasedOnTraceId() {
206     final Sampler defaultProbability = Samplers.probabilitySampler(0.0001);
207     // This traceId will not be sampled by the ProbabilitySampler because the first 8 bytes as long
208     // is not less than probability * Long.MAX_VALUE;
209     TraceId notSampledtraceId =
210         TraceId.fromBytes(
211             new byte[] {
212               (byte) 0x8F,
213               (byte) 0xFF,
214               (byte) 0xFF,
215               (byte) 0xFF,
216               (byte) 0xFF,
217               (byte) 0xFF,
218               (byte) 0xFF,
219               (byte) 0xFF,
220               0,
221               0,
222               0,
223               0,
224               0,
225               0,
226               0,
227               0
228             });
229     assertThat(
230             defaultProbability.shouldSample(
231                 null,
232                 false,
233                 notSampledtraceId,
234                 SpanId.generateRandomId(random),
235                 SPAN_NAME,
236                 Collections.<Span>emptyList()))
237         .isFalse();
238     // This traceId will be sampled by the ProbabilitySampler because the first 8 bytes as long
239     // is less than probability * Long.MAX_VALUE;
240     TraceId sampledtraceId =
241         TraceId.fromBytes(
242             new byte[] {
243               (byte) 0x00,
244               (byte) 0x00,
245               (byte) 0xFF,
246               (byte) 0xFF,
247               (byte) 0xFF,
248               (byte) 0xFF,
249               (byte) 0xFF,
250               (byte) 0xFF,
251               0,
252               0,
253               0,
254               0,
255               0,
256               0,
257               0,
258               0
259             });
260     assertThat(
261             defaultProbability.shouldSample(
262                 null,
263                 false,
264                 sampledtraceId,
265                 SpanId.generateRandomId(random),
266                 SPAN_NAME,
267                 Collections.<Span>emptyList()))
268         .isTrue();
269   }
270 
271   @Test
probabilitySampler_getDescription()272   public void probabilitySampler_getDescription() {
273     assertThat((Samplers.probabilitySampler(0.5)).getDescription())
274         .isEqualTo(String.format("ProbabilitySampler{%.6f}", 0.5));
275   }
276 
277   @Test
probabilitySampler_ToString()278   public void probabilitySampler_ToString() {
279     assertThat((Samplers.probabilitySampler(0.5)).toString()).contains("0.5");
280   }
281 }
282