package com.github.kristofa.brave;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.junit.Test;
import com.twitter.zipkin.gen.Span;
/**
* Integration isSampled for Brave api. Tests submitting server/client spans in parallel threads. Each thread represents a
* different trace. So this simulates having multiple parallel requests
*
* @author kristof
*/
public class ITBrave {
private final static int NUMBER_PARALLEL_THREADS = 4;
private final static int NUMBER_OF_REQUESTS = 1000;
@Test
public void testServerClientAndLocalSpanCycle() throws InterruptedException, ExecutionException {
final ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(NUMBER_PARALLEL_THREADS);
try {
final Collection<Future<Integer>> futures = new ArrayList<Future<Integer>>();
for (int index = 1; index <= NUMBER_OF_REQUESTS; index++) {
futures.add(newFixedThreadPool.submit(new SpanThread()));
}
for (final Future<Integer> future : futures) {
assertEquals(Integer.valueOf(2), future.get());
}
} finally {
newFixedThreadPool.shutdown();
}
}
class SpanThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
final IntegrationTestSpanCollector mockSpanCollector = new IntegrationTestSpanCollector();
final Brave.Builder builder = new Brave.Builder("serviceName");
final Brave brave = builder.spanCollector(mockSpanCollector).build();
final ServerTracer serverTracer = brave.serverTracer();
final Random random = new Random();
final String serverSpanName = "server span name " + random.nextLong();
SpanId spanId = SpanId.builder().spanId(random.nextLong()).build();
serverTracer.setStateCurrentTrace(spanId, serverSpanName);
serverTracer.setServerReceived();
serverTracer.submitAnnotation("custom annotation");
// Simulate client.
final ClientTracer clientTracer = brave.clientTracer();
final String clientSpanName = "client span name " + random.nextLong();
clientTracer.startNewSpan(clientSpanName);
clientTracer.setClientSent();
clientTracer.setClientReceived();
// Simulate local.
final LocalTracer localTracer = brave.localTracer();
final String localSpanName = "local span name " + random.nextLong();
localTracer.startNewSpan("test", localSpanName);
localTracer.finishSpan();
serverTracer.setServerSend();
final List<Span> collectedSpans = mockSpanCollector.getCollectedSpans();
assertEquals("Expected 3 collected spans.", 3, collectedSpans.size());
final Span clientSpan = collectedSpans.get(0);
final Span localSpan = collectedSpans.get(1);
final Span serverSpan = collectedSpans.get(2);
assertTrue(serverSpan.getTrace_id() != 0);
assertNull(serverSpan.getParent_id());
assertTrue(serverSpan.getId() != 0);
assertEquals(serverSpanName, serverSpan.getName());
assertEquals(serverSpan.getTrace_id(), clientSpan.getTrace_id());
assertEquals(serverSpan.getId(), clientSpan.getParent_id().longValue());
assertTrue(clientSpan.getId() != 0);
assertEquals(clientSpanName, clientSpan.getName());
assertEquals(serverSpan.getTrace_id(), localSpan.getTrace_id());
assertEquals(serverSpan.getId(), localSpan.getParent_id().longValue());
assertTrue(localSpan.getId() != 0);
assertEquals(localSpanName, localSpan.getName());
HashSet<Long> ids = new HashSet<Long>();
ids.add(serverSpan.getId());
ids.add(clientSpan.getId());
ids.add(localSpan.getId());
assertEquals("Span ids should be different.", 3, ids.size());
assertEquals("Expect sr, ss and 1 custom annotation.", 3, serverSpan.getAnnotations().size());
assertEquals(2, clientSpan.getAnnotations().size());
assertTrue(localSpan.getAnnotations().isEmpty());
return 2;
}
}
class IntegrationTestSpanCollector implements SpanCollector {
private final List<Span> collectedSpans = new ArrayList<Span>();
@Override
public void collect(final Span span) {
collectedSpans.add(span);
}
public List<Span> getCollectedSpans() {
return collectedSpans;
}
@Override
public void addDefaultAnnotation(final String name, final String value) {
throw new UnsupportedOperationException();
}
}
}