Ensure clients set X-Not-Sampled header for non-exportable Span

It also turns out that there's a bug in Spring MVC which makes an
empty header blow up in RequestHeaderMapMethodArgumentResolver
so we set the header to "true" instead of empty.

Fixes gh-136
This commit is contained in:
Dave Syer
2016-01-30 16:19:15 +00:00
parent 4f3c731d37
commit 39998a5def
17 changed files with 254 additions and 80 deletions

View File

@@ -299,7 +299,7 @@ public class Span {
@Override
public String toString() {
return "[Trace: " + toHex(this.traceId) + ", Span: " + toHex(this.spanId) + "]";
return "[Trace: " + toHex(this.traceId) + ", Span: " + toHex(this.spanId) + ", exportable=" + this.exportable + "]";
}
@Override

View File

@@ -52,7 +52,7 @@ public class SpanMessageHeaders {
if (span == null) {
if (!message.getHeaders().containsKey(Span.NOT_SAMPLED_NAME)) {
return MessageBuilder.fromMessage(message)
.setHeader(Span.NOT_SAMPLED_NAME, "").build();
.setHeader(Span.NOT_SAMPLED_NAME, "true").build();
}
return message;
}
@@ -71,7 +71,7 @@ public class SpanMessageHeaders {
addHeader(headers, Span.PROCESS_ID_NAME, span.getProcessId());
}
else {
addHeader(headers, Span.NOT_SAMPLED_NAME, "");
addHeader(headers, Span.NOT_SAMPLED_NAME, "true");
}
return MessageBuilder.fromMessage(message).copyHeaders(headers)
.setHeader(SPAN_HEADER, span).build();

View File

@@ -166,9 +166,6 @@ public class TraceFilter extends OncePerRequestFilter
request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest);
}
}
else {
this.tracer.continueSpan(spanFromRequest);
}
Throwable exception = null;
try {

View File

@@ -122,12 +122,15 @@ public class TraceFeignClientAutoConfiguration {
public void apply(RequestTemplate template) {
Span span = getCurrentSpan();
if (span == null) {
setHeader(template, Span.NOT_SAMPLED_NAME, "");
setHeader(template, Span.NOT_SAMPLED_NAME, "true");
return;
}
template.header(Span.TRACE_ID_NAME, Span.toHex(span.getTraceId()));
setHeader(template, Span.SPAN_NAME_NAME, span.getName());
setHeader(template, Span.SPAN_ID_NAME, Span.toHex(span.getSpanId()));
if (!span.isExportable()) {
setHeader(template, Span.NOT_SAMPLED_NAME, "true");
}
Long parentId = getParentId(span);
if (parentId != null) {
setHeader(template, Span.PARENT_ID_NAME, Span.toHex(parentId));
@@ -167,7 +170,7 @@ public class TraceFeignClientAutoConfiguration {
newHeaders.putAll(headers);
Span span = getCurrentSpan();
if (span == null) {
setHeader(newHeaders, Span.NOT_SAMPLED_NAME, "");
setHeader(newHeaders, Span.NOT_SAMPLED_NAME, "true");
return newHeaders;
}
setHeader(newHeaders, Span.TRACE_ID_NAME, span.getTraceId());

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.cloud.sleuth.instrument.web.client;
import java.io.IOException;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
@@ -26,9 +28,6 @@ import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StringUtils;
import java.io.IOException;
/**
* Interceptor that verifies whether the trance and span id has been set on the request
@@ -40,8 +39,8 @@ import java.io.IOException;
* @author Marcin Grzejszczak, 4financeIT
* @author Spencer Gibb
*/
public class TraceRestTemplateInterceptor implements ClientHttpRequestInterceptor,
ApplicationEventPublisherAware {
public class TraceRestTemplateInterceptor
implements ClientHttpRequestInterceptor, ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
@@ -61,11 +60,14 @@ ApplicationEventPublisherAware {
ClientHttpRequestExecution execution) throws IOException {
Span span = getCurrentSpan();
if (span == null) {
setHeader(request, Span.NOT_SAMPLED_NAME, "");
setHeader(request, Span.NOT_SAMPLED_NAME, "true");
return execution.execute(request, body);
}
setHeader(request, Span.TRACE_ID_NAME, span.getTraceId());
setHeader(request, Span.SPAN_ID_NAME, span.getSpanId());
if (!span.isExportable()) {
setHeader(request, Span.NOT_SAMPLED_NAME, "true");
}
setHeader(request, Span.SPAN_NAME_NAME, span.getName());
setHeader(request, Span.PARENT_ID_NAME, getParentId(span));
setHeader(request, Span.PROCESS_ID_NAME, span.getProcessId());
@@ -87,12 +89,11 @@ ApplicationEventPublisherAware {
}
private Long getParentId(Span span) {
return !span.getParents().isEmpty() ? span
.getParents().get(0) : null;
return !span.getParents().isEmpty() ? span.getParents().get(0) : null;
}
public void setHeader(HttpRequest request, String name, String value) {
if (StringUtils.hasText(value) && !request.getHeaders().containsKey(name) && this.accessor.isTracing()) {
if (value!=null && !request.getHeaders().containsKey(name) && this.accessor.isTracing()) {
request.getHeaders().add(name, value);
}
}

View File

@@ -16,8 +16,8 @@
package org.springframework.cloud.sleuth.instrument.zuul;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import java.util.Map;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
@@ -26,7 +26,8 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.util.ReflectionUtils;
import java.util.Map;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
/**
* @author Dave Syer
@@ -60,7 +61,7 @@ ApplicationEventPublisherAware {
// N.B. this will only work with the simple host filter (not ribbon) unless you set hystrix.execution.isolation.strategy=SEMAPHORE
Span span = getCurrentSpan();
if (span == null) {
setHeader(response, Span.NOT_SAMPLED_NAME, "");
setHeader(response, Span.NOT_SAMPLED_NAME, "true");
return null;
}
try {

View File

@@ -92,7 +92,7 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
protected void customizeRequest(HttpRequest.Builder requestBuilder) {
Span span = getCurrentSpan();
if (span == null) {
setHeader(requestBuilder, Span.NOT_SAMPLED_NAME, "");
setHeader(requestBuilder, Span.NOT_SAMPLED_NAME, "true");
return;
}
setHeader(requestBuilder, Span.TRACE_ID_NAME, Span.toHex(span.getTraceId()));

View File

@@ -69,9 +69,9 @@ public class DefaultTracer implements Tracer {
}
@Override
public Span startTrace(String name, Sampler s) {
public Span startTrace(String name, Sampler sampler) {
Span span;
if (isTracing() || s.isSampled()) {
if (isTracing() || sampler.isSampled()) {
span = createChild(getCurrentSpan(), name);
}
else {
@@ -144,12 +144,13 @@ public class DefaultTracer implements Tracer {
}
else {
if (SpanContextHolder.getCurrentSpan() == null) {
Span span = createSpan(null, parent);
Span span = createSpan(parent, null);
SpanContextHolder.setCurrentSpan(span);
}
Span span = Span.builder().begin(System.currentTimeMillis()).name(name)
.traceId(parent.getTraceId()).parent(parent.getSpanId()).spanId(id)
.processId(parent.getProcessId()).build();
.processId(parent.getProcessId()).exportable(parent.isExportable())
.build();
this.publisher.publishEvent(new SpanAcquiredEvent(this, parent, span));
return span;
}
@@ -164,12 +165,12 @@ public class DefaultTracer implements Tracer {
if (span != null) {
this.publisher.publishEvent(new SpanContinuedEvent(this, span));
}
Span newSpan = createSpan(SpanContextHolder.getCurrentSpan(), span);
Span newSpan = createSpan(span, SpanContextHolder.getCurrentSpan());
SpanContextHolder.setCurrentSpan(newSpan);
return newSpan;
}
protected Span createSpan(Span saved, Span span) {
protected Span createSpan(Span span, Span saved) {
if (saved == null && span.getSavedSpan() != null) {
saved = span.getSavedSpan();
}

View File

@@ -16,6 +16,18 @@
package org.springframework.cloud.sleuth;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -29,18 +41,6 @@ import org.springframework.cloud.sleuth.trace.SpanContextHolder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/**
* @author Spencer Gibb
*/
@@ -50,10 +50,12 @@ public class DefaultTraceManagerTests {
public static final String IMPORTANT_WORK_1 = "important work 1";
public static final String IMPORTANT_WORK_2 = "important work 2";
public static final int NUM_SPANS = 3;
private ApplicationEventPublisher publisher;
@Before
public void setup() {
SpanContextHolder.removeCurrentSpan();
this.publisher = mock(ApplicationEventPublisher.class);
}
@After
@@ -63,24 +65,23 @@ public class DefaultTraceManagerTests {
@Test
public void tracingWorks() {
ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class);
DefaultTracer traceManager = new DefaultTracer(new IsTracingSampler(), new Random(), publisher);
DefaultTracer tracer = new DefaultTracer(new IsTracingSampler(), new Random(), this.publisher);
Span span = traceManager.startTrace(CREATE_SIMPLE_TRACE, new AlwaysSampler());
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE, new AlwaysSampler());
try {
importantWork1(traceManager);
importantWork1(tracer);
}
finally {
traceManager.close(span);
tracer.close(span);
}
verify(publisher, times(NUM_SPANS)).publishEvent(isA(SpanAcquiredEvent.class));
verify(publisher, times(NUM_SPANS)).publishEvent(isA(SpanReleasedEvent.class));
verify(this.publisher, times(NUM_SPANS)).publishEvent(isA(SpanAcquiredEvent.class));
verify(this.publisher, times(NUM_SPANS)).publishEvent(isA(SpanReleasedEvent.class));
ArgumentCaptor<ApplicationEvent> captor = ArgumentCaptor
.forClass(ApplicationEvent.class);
verify(publisher, atLeast(NUM_SPANS)).publishEvent(captor.capture());
verify(this.publisher, atLeast(NUM_SPANS)).publishEvent(captor.capture());
List<Span> spans = new ArrayList<>();
for (ApplicationEvent event : captor.getAllValues()) {
@@ -99,6 +100,22 @@ public class DefaultTraceManagerTests {
assertThat("gen4 was non-empty", gen4.isEmpty(), is(true));
}
@Test
public void nonExportable() {
DefaultTracer tracer = new DefaultTracer(new IsTracingSampler(), new Random(), this.publisher);
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE);
assertThat(span.isExportable(), is(false));
}
@Test
public void exportableInheritedFromParent() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher);
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE, new IsTracingSampler());
assertThat(span.isExportable(), is(false));
Span child = tracer.joinTrace(CREATE_SIMPLE_TRACE + "/child", span);
assertThat(child.isExportable(), is(false));
}
private Span assertSpan(List<Span> spans, Long parentId, String name) {
List<Span> found = findSpans(spans, parentId);
assertThat("more than one span with parentId " + parentId, found.size(), is(1));

View File

@@ -10,10 +10,8 @@ import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.integration.TraceSpringIntegrationAutoConfiguration;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@@ -21,7 +19,6 @@ import org.springframework.context.annotation.Import;
JmxAutoConfiguration.class, TraceSpringIntegrationAutoConfiguration.class,
ArchaiusAutoConfiguration.class, LoadBalancerAutoConfiguration.class })
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Import(AlwaysSampler.class)
@Configuration
public @interface DefaultTestAutoConfiguration {
}

View File

@@ -16,6 +16,12 @@
package org.springframework.cloud.sleuth.instrument.integration;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.util.ArrayList;
import java.util.List;
@@ -46,12 +52,6 @@ import org.springframework.messaging.MessagingException;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
/**
* @author Dave Syer
*/
@@ -98,7 +98,7 @@ public class TraceChannelInterceptorTests implements MessageHandler {
@Test
public void nonExportableSpanCreation() {
this.channel.send(MessageBuilder.withPayload("hi")
.setHeader(Span.NOT_SAMPLED_NAME, "").build());
.setHeader(Span.NOT_SAMPLED_NAME, "true").build());
assertNotNull("message was null", this.message);
String spanId = this.message.getHeaders().get(Span.SPAN_ID_NAME, String.class);

View File

@@ -0,0 +1,109 @@
package org.springframework.cloud.sleuth.instrument.web;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.cloud.sleuth.instrument.web.common.AbstractMvcIntegrationTest;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(TraceFilterAlwaysSamplerIntegrationTests.class)
@DefaultTestAutoConfiguration
@RestController
@Configuration
@Import(AlwaysSampler.class)
public class TraceFilterAlwaysSamplerIntegrationTests extends AbstractMvcIntegrationTest {
private static Log logger = LogFactory
.getLog(TraceFilterAlwaysSamplerIntegrationTests.class);
@Autowired
Tracer tracer;
@Autowired
TraceKeys traceKeys;
static Span span;
@RequestMapping("/ping")
public String ping() {
logger.info("ping");
span = this.tracer.getCurrentSpan();
return "ping";
}
@Test
public void when_always_sampler_is_used_span_is_exportable() throws Exception {
Long expectedTraceId = new Random().nextLong();
MvcResult mvcResult = whenSentPingWithTraceId(expectedTraceId);
then(tracingHeaderFrom(mvcResult)).isEqualTo(expectedTraceId);
then(span.isExportable());
}
@Test
public void when_not_sampling_header_present_span_is_not_exportable() throws Exception {
Long expectedTraceId = new Random().nextLong();
MvcResult mvcResult = whenSentPingWithTraceIdAndNotSampling(expectedTraceId);
then(tracingHeaderFrom(mvcResult)).isEqualTo(expectedTraceId);
then(span.isExportable()).isFalse();
}
@Override
protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) {
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys));
}
private MvcResult whenSentPingWithTraceIdAndNotSampling(Long traceId)
throws Exception {
return sendPingWithTraceId(Span.TRACE_ID_NAME, traceId, false);
}
private MvcResult whenSentPingWithTraceId(Long traceId) throws Exception {
return sendPingWithTraceId(Span.TRACE_ID_NAME, traceId);
}
private MvcResult sendPingWithTraceId(String headerName, Long correlationId)
throws Exception {
return sendPingWithTraceId(headerName, correlationId, true);
}
private MvcResult sendPingWithTraceId(String headerName, Long correlationId,
boolean sampling) throws Exception {
MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/ping")
.accept(MediaType.TEXT_PLAIN)
.header(headerName, Span.toHex(correlationId))
.header(Span.SPAN_ID_NAME, Span.toHex(new Random().nextLong()));
if (!sampling) {
request.header(Span.NOT_SAMPLED_NAME, "true");
}
return this.mockMvc.perform(request).andReturn();
}
private Long tracingHeaderFrom(MvcResult mvcResult) {
return Span.fromHex(mvcResult.getResponse().getHeader(Span.TRACE_ID_NAME));
}
}

View File

@@ -39,9 +39,12 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
@Autowired
TraceKeys traceKeys;
static Span span;
@RequestMapping("/ping")
public String ping() {
logger.info("ping");
span = this.tracer.getCurrentSpan();
return "ping";
}

View File

@@ -72,8 +72,8 @@ public class TraceFilterTests {
this.tracer = new DefaultTracer(new DelegateSampler(), new Random(),
this.publisher) {
@Override
protected Span createSpan(Span saved, Span span) {
TraceFilterTests.this.span = super.createSpan(saved, span);
protected Span createSpan(Span span, Span saved) {
TraceFilterTests.this.span = super.createSpan(span, saved);
return TraceFilterTests.this.span;
}
};

View File

@@ -1,8 +1,14 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -23,6 +29,7 @@ import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.test.annotation.DirtiesContext;
@@ -32,12 +39,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { FeignTraceTests.TestConfiguration.class })
@@ -70,6 +74,22 @@ public class FeignTraceTests {
then(this.listener.getEvents()).isNotEmpty();
}
@Test
public void shouldPropagateNotSamplingHeader() {
// given
Long currentTraceId = 1L;
Long currentParentId = 2L;
this.tracer.continueSpan(Span.builder().traceId(currentTraceId)
.spanId(generatedId()).exportable(false).parent(currentParentId).build());
// when
ResponseEntity<Map<String, String>> response = this.testFeignInterface.headers();
// then
then(response.getBody().get(Span.TRACE_ID_NAME)).isNotNull();
then(response.getBody().get(Span.NOT_SAMPLED_NAME)).isNotNull();
then(this.listener.getEvents()).isNotEmpty();
}
@Test
public void shouldAttachTraceIdWhenUsingFeignClient() {
// given
@@ -82,7 +102,8 @@ public class FeignTraceTests {
ResponseEntity<String> response = this.testFeignInterface.getTraceId();
// then
then(Span.fromHex(getHeader(response, Span.TRACE_ID_NAME))).isEqualTo(currentTraceId);
then(Span.fromHex(getHeader(response, Span.TRACE_ID_NAME)))
.isEqualTo(currentTraceId);
then(this.listener.getEvents().size()).isEqualTo(2);
}
@@ -102,6 +123,9 @@ public class FeignTraceTests {
@RequestMapping(method = RequestMethod.GET, value = "/notrace")
ResponseEntity<String> getNoTrace();
@RequestMapping(method = RequestMethod.GET, value = "/")
ResponseEntity<Map<String, String>> headers();
}
@Configuration
@@ -159,6 +183,16 @@ public class FeignTraceTests {
then(spanId).isNotEmpty();
return traceId;
}
@RequestMapping("/")
public Map<String, String> home(@RequestHeader HttpHeaders headers) {
Map<String, String> map = new HashMap<String, String>();
for (String key : headers.keySet()) {
map.put(key, headers.getFirst(key));
}
return map;
}
}
@Configuration

View File

@@ -16,6 +16,14 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertFalse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -34,14 +42,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertFalse;
/**
* @author Dave Syer
*
@@ -82,6 +82,17 @@ public class TraceRestTemplateInterceptorTests {
then(Long.valueOf(headers.get(Span.SPAN_ID_NAME))).isEqualTo(2L);
}
@Test
public void notSampledHeaderAddedWhenNotExportable() {
this.traces.continueSpan(Span.builder().traceId(1L).spanId(2L).exportable(false).build());
@SuppressWarnings("unchecked")
Map<String, String> headers = this.template.getForEntity("/", Map.class)
.getBody();
then(Long.valueOf(headers.get(Span.TRACE_ID_NAME))).isEqualTo(1L);
then(Long.valueOf(headers.get(Span.SPAN_ID_NAME))).isEqualTo(2L);
then(headers.get(Span.NOT_SAMPLED_NAME)).isEqualTo("true");
}
@Test
public void headersNotAddedWhenNotTracing() {
@SuppressWarnings("unchecked")
@@ -96,7 +107,7 @@ public class TraceRestTemplateInterceptorTests {
public Map<String, String> home(@RequestHeader HttpHeaders headers) {
Map<String, String> map = new HashMap<String, String>();
addHeaders(map, headers, Span.SPAN_ID_NAME, Span.TRACE_ID_NAME,
Span.PARENT_ID_NAME);
Span.PARENT_ID_NAME, Span.NOT_SAMPLED_NAME);
return map;
}

View File

@@ -62,7 +62,7 @@ public class SleuthStreamAutoConfiguration {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
return MessageBuilder.fromMessage(message)
.setHeader(Span.NOT_SAMPLED_NAME, "").build();
.setHeader(Span.NOT_SAMPLED_NAME, "true").build();
}
@Override