Add Span to Sampler method params
Also allows us to actually create a PercentageBasedSampler (I don't think anyone tried it before) without resorting to lazy beans and proxies. Another freature added here is a default percentage sampler if we know that spans need to be exported (zipkin or stream is present). Fixes gh-138
This commit is contained in:
@@ -17,8 +17,11 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
|
||||
/**
|
||||
* Extremely simple callback to determine the frequency that an action should be
|
||||
* Extremely simple callback to determine the frequency that an action should be traced.
|
||||
*/
|
||||
public interface Sampler {
|
||||
boolean isSampled();
|
||||
/**
|
||||
* @param span the current span (or null if there is none)
|
||||
*/
|
||||
boolean isSampled(Span span);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
package org.springframework.cloud.sleuth.sampler;
|
||||
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class AlwaysSampler implements Sampler {
|
||||
@Override
|
||||
public boolean isSampled() {
|
||||
public boolean isSampled(Span span) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.sleuth.sampler;
|
||||
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.trace.SpanContextHolder;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ public class IsTracingSampler implements Sampler {
|
||||
public static IsTracingSampler INSTANCE = new IsTracingSampler();
|
||||
|
||||
@Override
|
||||
public boolean isSampled() {
|
||||
public boolean isSampled(Span span) {
|
||||
return SpanContextHolder.isTracing();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.springframework.cloud.sleuth.sampler;
|
||||
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
|
||||
/**
|
||||
* Sampler that based on the given percentage rate will allow sampling.
|
||||
@@ -23,16 +22,13 @@ import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
public class PercentageBasedSampler implements Sampler {
|
||||
|
||||
private final SamplerConfiguration configuration;
|
||||
private final SpanAccessor spanAccessor;
|
||||
|
||||
public PercentageBasedSampler(SamplerConfiguration configuration, SpanAccessor spanAccessor) {
|
||||
public PercentageBasedSampler(SamplerConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
this.spanAccessor = spanAccessor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSampled() {
|
||||
Span currentSpan = this.spanAccessor.getCurrentSpan();
|
||||
public boolean isSampled(Span currentSpan) {
|
||||
long threshold = Math.abs(Long.MAX_VALUE * (int) (this.configuration.getPercentage() * 100)); // drops fractional percentage.
|
||||
if (currentSpan == null || threshold == 0L) {
|
||||
return false;
|
||||
|
||||
@@ -13,15 +13,9 @@ import lombok.Data;
|
||||
public class SamplerConfiguration {
|
||||
|
||||
/**
|
||||
* Percentage of requests that should be sampled.
|
||||
* E.g.
|
||||
* <ul>
|
||||
* <li> 1.0 - 100% requests should be sampled </li>
|
||||
* <li> 0.8 - 80% of requests should be sampled </li>
|
||||
* <li> 0.0 - 0% requests should be sampled </li>
|
||||
* </ul>
|
||||
*
|
||||
* The precision is whole-numbers only. We don't support 0.1% of the trace rate.
|
||||
* Percentage of requests that should be sampled. E.g. 1.0 - 100% requests should be
|
||||
* sampled. The precision is whole-numbers only (i.e. there's no support for 0.1% of
|
||||
* the traces).
|
||||
*/
|
||||
private float percentage = 0.1f;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class DefaultTracer implements Tracer {
|
||||
@Override
|
||||
public Span startTrace(String name, Sampler sampler) {
|
||||
Span span;
|
||||
if (isTracing() || sampler.isSampled()) {
|
||||
if (isTracing() || sampler.isSampled(getCurrentSpan())) {
|
||||
span = createChild(getCurrentSpan(), name);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -16,7 +16,16 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
@@ -37,15 +46,7 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -216,8 +217,8 @@ public class TraceFilterTests {
|
||||
|
||||
private class DelegateSampler implements Sampler {
|
||||
@Override
|
||||
public boolean isSampled() {
|
||||
return TraceFilterTests.this.sampler.isSampled();
|
||||
public boolean isSampled(Span span) {
|
||||
return TraceFilterTests.this.sampler.isSampled(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package org.springframework.cloud.sleuth.sampler;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.assertj.core.data.Percentage.withPercentage;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
public class PercentageBasedSamplerTests {
|
||||
|
||||
SamplerConfiguration samplerConfiguration = new SamplerConfiguration();
|
||||
SpanAccessor spanAccessor = traceReturningSpanWithUuid();
|
||||
private Span span;
|
||||
private static Random RANDOM = new Random();
|
||||
|
||||
@Test
|
||||
@@ -20,17 +20,20 @@ public class PercentageBasedSamplerTests {
|
||||
this.samplerConfiguration.setPercentage(1f);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
then(new PercentageBasedSampler(this.samplerConfiguration, this.spanAccessor).isSampled()).isTrue();
|
||||
then(new PercentageBasedSampler(this.samplerConfiguration).isSampled(this.span))
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_reject_all_samples_when_config_has_0_percentage() throws Exception {
|
||||
public void should_reject_all_samples_when_config_has_0_percentage()
|
||||
throws Exception {
|
||||
this.samplerConfiguration.setPercentage(0f);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
then(new PercentageBasedSampler(this.samplerConfiguration, this.spanAccessor).isSampled()).isFalse();
|
||||
then(new PercentageBasedSampler(this.samplerConfiguration).isSampled(this.span))
|
||||
.isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,30 +45,23 @@ public class PercentageBasedSamplerTests {
|
||||
|
||||
int numberOfSampledElements = countNumberOfSampledElements(numberOfIterations);
|
||||
|
||||
then(numberOfSampledElements).isCloseTo((int) (numberOfIterations * percentage), withPercentage(3));
|
||||
then(numberOfSampledElements).isCloseTo((int) (numberOfIterations * percentage),
|
||||
withPercentage(3));
|
||||
}
|
||||
|
||||
private int countNumberOfSampledElements(int numberOfIterations) {
|
||||
int passedCounter = 0;
|
||||
for (int i = 0; i < numberOfIterations; i++) {
|
||||
boolean passed = new PercentageBasedSampler(this.samplerConfiguration, traceReturningSpanWithUuid()).isSampled();
|
||||
boolean passed = new PercentageBasedSampler(this.samplerConfiguration)
|
||||
.isSampled(this.span);
|
||||
passedCounter = passedCounter + (passed ? 1 : 0);
|
||||
}
|
||||
return passedCounter;
|
||||
}
|
||||
|
||||
private SpanAccessor traceReturningSpanWithUuid() {
|
||||
return new SpanAccessor() {
|
||||
@Override
|
||||
public Span getCurrentSpan() {
|
||||
return Span.builder().traceId(RANDOM.nextLong()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTracing() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@Before
|
||||
public void setupSpan() {
|
||||
this.span = Span.builder().traceId(RANDOM.nextLong()).build();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user