Improving test coverage + minor fix

This commit is contained in:
Guillaume Polaert 2017-06-26 17:10:48 -04:00
parent aadc526338
commit 43065257ca
10 changed files with 261 additions and 171 deletions

View File

@ -1,7 +1,6 @@
package com.datadoghq.trace.propagation;
import com.datadoghq.trace.DDSpanContext;
import io.opentracing.propagation.TextMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -18,86 +17,86 @@ import java.util.Map;
*/
public class HTTPCodec implements Codec<TextMap> {
private static final String OT_PREFIX = "ot-tracer-";
private static final String OT_BAGGAGE_PREFIX = "ot-baggage-";
private static final String TRACE_ID_KEY = OT_PREFIX + "traceid";
private static final String SPAN_ID_KEY = OT_PREFIX + "spanid";
private static final String OT_PREFIX = "ot-tracer-";
private static final String OT_BAGGAGE_PREFIX = "ot-baggage-";
private static final String TRACE_ID_KEY = OT_PREFIX + "traceid";
private static final String SPAN_ID_KEY = OT_PREFIX + "spanid";
private static final Logger logger = LoggerFactory.getLogger(HTTPCodec.class);
private static final Logger logger = LoggerFactory.getLogger(HTTPCodec.class);
@Override
public void inject(DDSpanContext context, TextMap carrier) {
@Override
public void inject(DDSpanContext context, TextMap carrier) {
carrier.put(TRACE_ID_KEY, String.valueOf(context.getTraceId()));
carrier.put(SPAN_ID_KEY, String.valueOf(context.getSpanId()));
carrier.put(TRACE_ID_KEY, String.valueOf(context.getTraceId()));
carrier.put(SPAN_ID_KEY, String.valueOf(context.getSpanId()));
for (Map.Entry<String, String> entry : context.baggageItems()) {
carrier.put(OT_BAGGAGE_PREFIX + entry.getKey(), encode(entry.getValue()));
}
}
for (Map.Entry<String, String> entry : context.baggageItems()) {
carrier.put(OT_BAGGAGE_PREFIX + entry.getKey(), encode(entry.getValue()));
}
}
@Override
public DDSpanContext extract(TextMap carrier) {
@Override
public DDSpanContext extract(TextMap carrier) {
Map<String, String> baggage = Collections.emptyMap();
Long traceId = 0L;
Long spanId = 0L;
Map<String, String> baggage = Collections.emptyMap();
Long traceId = 0L;
Long spanId = 0L;
for (Map.Entry<String, String> entry : carrier) {
for (Map.Entry<String, String> entry : carrier) {
if (entry.getKey().equals(TRACE_ID_KEY)) {
traceId = Long.parseLong(entry.getValue());
} else if (entry.getKey().equals(SPAN_ID_KEY)) {
spanId = Long.parseLong(entry.getValue());
} else if (entry.getKey().startsWith(OT_BAGGAGE_PREFIX)) {
if (baggage.isEmpty()) {
baggage = new HashMap<String, String>();
}
baggage.put(entry.getKey(), decode(entry.getValue()));
}
}
DDSpanContext context = null;
if (traceId != 0L) {
if (entry.getKey().equals(TRACE_ID_KEY)) {
traceId = Long.parseLong(entry.getValue());
} else if (entry.getKey().equals(SPAN_ID_KEY)) {
spanId = Long.parseLong(entry.getValue());
} else if (entry.getKey().startsWith(OT_BAGGAGE_PREFIX)) {
if (baggage.isEmpty()) {
baggage = new HashMap<String, String>();
}
baggage.put(entry.getKey().replace(OT_BAGGAGE_PREFIX, ""), decode(entry.getValue()));
}
}
DDSpanContext context = null;
if (traceId != 0L) {
context = new DDSpanContext(
traceId,
spanId,
0L,
null,
null,
null,
baggage,
false,
null,
null,
null,
null);
context = new DDSpanContext(
traceId,
spanId,
0L,
null,
null,
null,
baggage,
false,
null,
null,
null,
null);
logger.debug("{} - Parent context extracted", context);
}
logger.debug("{} - Parent context extracted", context);
}
return context;
}
return context;
}
private String encode(String value) {
String encoded = value;
try {
encoded = URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.info("Failed to encode value - {}", value);
}
return encoded;
}
private String encode(String value) {
String encoded = value;
try {
encoded = URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.info("Failed to encode value - {}", value);
}
return encoded;
}
private String decode(String value) {
String decoded = value;
try {
decoded = URLDecoder.decode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.info("Failed to decode value - {}", value);
}
return decoded;
}
private String decode(String value) {
String decoded = value;
try {
decoded = URLDecoder.decode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.info("Failed to decode value - {}", value);
}
return decoded;
}
}

View File

@ -1,7 +1,7 @@
package com.datadoghq.trace.resolver;
import com.datadoghq.trace.DDTracer;
import com.datadoghq.trace.sampling.ASampler;
import com.datadoghq.trace.sampling.AbstractSampler;
import com.datadoghq.trace.sampling.AllSampler;
import com.datadoghq.trace.sampling.RateSampler;
import com.datadoghq.trace.sampling.Sampler;
@ -74,8 +74,8 @@ public class DDTracerFactory {
//Add sampled tags
Map<String, String> skipTagsPatterns = config.getSampler().getSkipTagsPatterns();
if (skipTagsPatterns != null && sampler instanceof ASampler) {
ASampler aSampler = (ASampler) sampler;
if (skipTagsPatterns != null && sampler instanceof AbstractSampler) {
AbstractSampler aSampler = (AbstractSampler) sampler;
for (Map.Entry<String, String> entry : skipTagsPatterns.entrySet()) {
aSampler.addSkipTagPattern(entry.getKey(), Pattern.compile(entry.getValue()));
}

View File

@ -1,13 +1,13 @@
package com.datadoghq.trace.sampling;
import com.datadoghq.trace.DDBaseSpan;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import com.datadoghq.trace.DDBaseSpan;
public abstract class ASampler implements Sampler{
public abstract class AbstractSampler implements Sampler {
/**
* Sample tags

View File

@ -5,7 +5,7 @@ import com.datadoghq.trace.DDBaseSpan;
/**
* Sampler that always says yes...
*/
public class AllSampler extends ASampler {
public class AllSampler extends AbstractSampler {
@Override
public boolean doSample(DDBaseSpan<?> span) {

View File

@ -1,11 +1,10 @@
package com.datadoghq.trace.sampling;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datadoghq.trace.DDBaseSpan;
import com.google.auto.service.AutoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
@ -15,7 +14,7 @@ import com.google.auto.service.AutoService;
* It samples randomly, its main purpose is to reduce the instrumentation footprint.
*/
@AutoService(Sampler.class)
public class RateSampler extends ASampler {
public class RateSampler extends AbstractSampler {
private final static Logger logger = LoggerFactory.getLogger(RateSampler.class);

View File

@ -1,54 +0,0 @@
import com.datadoghq.trace.DDTracer;
import com.datadoghq.trace.sampling.AllSampler;
import com.datadoghq.trace.sampling.Sampler;
import com.datadoghq.trace.writer.DDAgentWriter;
import com.datadoghq.trace.writer.Writer;
import io.opentracing.Span;
public class ExampleWithDDAgentWriter {
public static void main(String[] args) throws Exception {
// Instantiate the DDWriter
// By default, traces are written to localhost:8126 (the ddagent)
Writer writer = new DDAgentWriter();
// Instantiate the proper Sampler
// - RateSampler if you want to keep `ratio` traces
// - AllSampler to keep all traces
Sampler sampler = new AllSampler();
// Create the tracer
DDTracer tracer = new DDTracer(writer, sampler);
Span parent = tracer
.buildSpan("hello-world")
.withServiceName("service-name")
.withSpanType("web")
.start();
Thread.sleep(100);
parent.setBaggageItem("a-baggage", "value");
Span child = tracer
.buildSpan("hello-world")
.asChildOf(parent)
.withResourceName("resource-name")
.start();
Thread.sleep(100);
child.finish();
Thread.sleep(100);
parent.finish();
writer.close();
}
}

View File

@ -1,38 +0,0 @@
package com.datadoghq.trace;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.junit.Test;
import com.datadoghq.trace.sampling.AllSampler;
public class AllSamplerTest {
@Test
public void testAllSampler() {
AllSampler sampler = new AllSampler();
sampler.addSkipTagPattern("http.url", Pattern.compile(".*/hello"));
DDSpan mockSpan = mock(DDSpan.class);
Map<String,Object> tags = new HashMap<String,Object>();
tags.put("http.url", "http://a/hello");
when(mockSpan.getTags()).thenReturn(tags).thenReturn(tags);
assertThat(sampler.sample(mockSpan)).isEqualTo(false);
tags.put("http.url", "http://a/hello2");
assertThat(sampler.sample(mockSpan)).isEqualTo(true);
}
}

View File

@ -0,0 +1,84 @@
package com.datadoghq.trace.propagation;
import com.datadoghq.trace.DDSpanContext;
import io.opentracing.propagation.TextMapExtractAdapter;
import io.opentracing.propagation.TextMapInjectAdapter;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Java6Assertions.assertThat;
/**
* Created by gpolaert on 6/23/17.
*/
public class HTTPCodecTest {
private static final String OT_PREFIX = "ot-tracer-";
private static final String OT_BAGGAGE_PREFIX = "ot-baggage-";
private static final String TRACE_ID_KEY = OT_PREFIX + "traceid";
private static final String SPAN_ID_KEY = OT_PREFIX + "spanid";
@Test
public void shoudAddHttpHeaders() {
DDSpanContext mockedContext = new DDSpanContext(
1L,
2L,
0L,
"fakeService",
"fakeOperation",
"fakeResource",
new HashMap<String, String>() {{
put("k1", "v1");
put("k2", "v2");
}},
false,
"fakeType",
null,
null,
null);
Map<String, String> carrier = new HashMap<>();
HTTPCodec codec = new HTTPCodec();
codec.inject(mockedContext, new TextMapInjectAdapter(carrier));
assertThat(carrier.get(TRACE_ID_KEY)).isEqualTo("1");
assertThat(carrier.get(SPAN_ID_KEY)).isEqualTo("2");
assertThat(carrier.get(OT_BAGGAGE_PREFIX + "k1")).isEqualTo("v1");
assertThat(carrier.get(OT_BAGGAGE_PREFIX + "k2")).isEqualTo("v2");
}
@Test
public void shoudReadHttpHeaders() {
Map<String, String> actual = new HashMap<String, String>() {{
put(TRACE_ID_KEY, "1");
put(SPAN_ID_KEY, "2");
put(OT_BAGGAGE_PREFIX + "k1", "v1");
put(OT_BAGGAGE_PREFIX + "k2", "v2");
}};
HTTPCodec codec = new HTTPCodec();
DDSpanContext context = codec.extract(new TextMapExtractAdapter(actual));
assertThat(context.getTraceId()).isEqualTo(1l);
assertThat(context.getSpanId()).isEqualTo(2l);
assertThat(context.getBaggageItem("k1")).isEqualTo("v1");
assertThat(context.getBaggageItem("k2")).isEqualTo("v2");
}
}

View File

@ -0,0 +1,47 @@
package com.datadoghq.trace.sampling;
import com.datadoghq.trace.DDSpan;
import org.junit.Test;
import org.mockito.Mock;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class AllSamplerTest {
@Mock
DDSpan mockSpan;
private final AllSampler sampler = new AllSampler();
@Test
public void testAllSampler() {
for (int i = 0; i < 500; i++) {
assertThat(sampler.doSample(mockSpan)).isTrue();
}
}
@Test
public void testSkipTagPatternSampler() {
Map<String, Object> tags = new HashMap<>();
mockSpan = mock(DDSpan.class);
when(mockSpan.getTags()).thenReturn(tags).thenReturn(tags);
sampler.addSkipTagPattern("http.url", Pattern.compile(".*/hello"));
tags.put("http.url", "http://a/hello");
assertThat(sampler.sample(mockSpan)).isFalse();
tags.put("http.url", "http://a/hello2");
assertThat(sampler.sample(mockSpan)).isTrue();
}
}

View File

@ -0,0 +1,53 @@
package com.datadoghq.trace.sampling;
import com.datadoghq.trace.DDTracer;
import com.datadoghq.trace.writer.DDAgentWriter;
import com.datadoghq.trace.writer.Writer;
import io.opentracing.Span;
public class ExampleWithDDAgentWriter {
public static void main(String[] args) throws Exception {
// Instantiate the DDWriter
// By default, traces are written to localhost:8126 (the ddagent)
Writer writer = new DDAgentWriter();
// Instantiate the proper Sampler
// - RateSampler if you want to keep `ratio` traces
// - AllSampler to keep all traces
Sampler sampler = new AllSampler();
// Create the tracer
DDTracer tracer = new DDTracer(writer, sampler);
Span parent = tracer
.buildSpan("hello-world")
.withServiceName("service-name")
.withSpanType("web")
.start();
Thread.sleep(100);
parent.setBaggageItem("a-baggage", "value");
Span child = tracer
.buildSpan("hello-world")
.asChildOf(parent)
.withResourceName("resource-name")
.start();
Thread.sleep(100);
child.finish();
Thread.sleep(100);
parent.finish();
writer.close();
}
}