Search in sources :

Example 31 with Span

use of zipkin.Span in project zipkin by openzipkin.

the class SpanStoreTest method correctsClockSkew.

/**
   * Basic clock skew correction is something span stores should support, until the UI supports
   * happens-before without using timestamps. The easiest clock skew to correct is where a child
   * appears to happen before the parent.
   *
   * <p>It doesn't matter if clock-skew correction happens at store or query time, as long as it
   * occurs by the time results are returned.
   *
   * <p>Span stores who don't support this can override and disable this test, noting in the README
   * the limitation.
   */
@Test
public void correctsClockSkew() {
    Endpoint client = Endpoint.create("client", 192 << 24 | 168 << 16 | 1);
    Endpoint frontend = Endpoint.create("frontend", 192 << 24 | 168 << 16 | 2);
    Endpoint backend = Endpoint.create("backend", 192 << 24 | 168 << 16 | 3);
    /** Intentionally not setting span.timestamp, duration */
    Span parent = Span.builder().traceId(1).name("method1").id(666).addAnnotation(Annotation.create((today + 100) * 1000, CLIENT_SEND, client)).addAnnotation(// before client sends
    Annotation.create((today + 95) * 1000, SERVER_RECV, frontend)).addAnnotation(// before client receives
    Annotation.create((today + 120) * 1000, SERVER_SEND, frontend)).addAnnotation(Annotation.create((today + 135) * 1000, CLIENT_RECV, client)).build();
    /** Intentionally not setting span.timestamp, duration */
    Span remoteChild = Span.builder().traceId(1).name("method2").id(777).parentId(666L).addAnnotation(Annotation.create((today + 100) * 1000, CLIENT_SEND, frontend)).addAnnotation(Annotation.create((today + 115) * 1000, SERVER_RECV, backend)).addAnnotation(Annotation.create((today + 120) * 1000, SERVER_SEND, backend)).addAnnotation(// before server sent
    Annotation.create((today + 115) * 1000, CLIENT_RECV, frontend)).build();
    /** Local spans must explicitly set timestamp */
    Span localChild = Span.builder().traceId(1).name("local").id(778).parentId(666L).timestamp((today + 101) * 1000).duration(50L).addBinaryAnnotation(BinaryAnnotation.create(LOCAL_COMPONENT, "framey", frontend)).build();
    List<Span> skewed = asList(parent, remoteChild, localChild);
    // There's clock skew when the child doesn't happen after the parent
    assertThat(skewed.get(0).annotations.get(0).timestamp).isLessThanOrEqualTo(skewed.get(1).annotations.get(0).timestamp).isLessThanOrEqualTo(// local span
    skewed.get(2).timestamp);
    // Regardless of when clock skew is corrected, it should be corrected before traces return
    accept(parent, remoteChild, localChild);
    List<Span> adjusted = store().getTrace(localChild.traceIdHigh, localChild.traceId);
    // After correction, the child happens after the parent
    assertThat(adjusted.get(0).timestamp).isLessThanOrEqualTo(adjusted.get(0).timestamp);
    // After correction, children happen after their parent
    assertThat(adjusted.get(0).timestamp).isLessThanOrEqualTo(adjusted.get(1).timestamp).isLessThanOrEqualTo(adjusted.get(2).timestamp);
    // And we do not change the parent (client) duration, due to skew in the child (server)
    assertThat(adjusted.get(0).duration).isEqualTo(clientDuration(skewed.get(0)));
    assertThat(adjusted.get(1).duration).isEqualTo(clientDuration(skewed.get(1)));
    assertThat(adjusted.get(2).duration).isEqualTo(skewed.get(2).duration);
}
Also used : Endpoint(zipkin.Endpoint) Span(zipkin.Span) Test(org.junit.Test)

Example 32 with Span

use of zipkin.Span in project zipkin by openzipkin.

the class SpanStoreTest method getTraces_mergesSpans.

/**
   * It is expected that [[com.twitter.zipkin.storage.SpanStore.apply]] will receive the same span
   * id multiple times with different annotations. At query time, these must be merged.
   */
@Test
public void getTraces_mergesSpans() {
    // span4, span5 have the same span id
    accept(span1, span4, span5);
    SortedSet<Annotation> mergedAnnotations = new TreeSet<>(span4.annotations);
    mergedAnnotations.addAll(span5.annotations);
    Span merged = span4.toBuilder().timestamp(mergedAnnotations.first().timestamp).duration(mergedAnnotations.last().timestamp - mergedAnnotations.first().timestamp).annotations(mergedAnnotations).binaryAnnotations(span5.binaryAnnotations).build();
    assertThat(store().getTraces(QueryRequest.builder().serviceName("service").build())).containsExactly(asList(merged), asList(span1));
}
Also used : TreeSet(java.util.TreeSet) Span(zipkin.Span) Annotation(zipkin.Annotation) BinaryAnnotation(zipkin.BinaryAnnotation) Test(org.junit.Test)

Example 33 with Span

use of zipkin.Span in project zipkin by openzipkin.

the class SpanStoreTest method getTraces_duration.

/** Shows that duration queries go against the root span, not the child */
@Test
public void getTraces_duration() {
    Endpoint service1 = Endpoint.create("service1", 127 << 24 | 1);
    Endpoint service2 = Endpoint.create("service2", 127 << 24 | 2);
    Endpoint service3 = Endpoint.create("service3", 127 << 24 | 3);
    BinaryAnnotation.Builder component = BinaryAnnotation.builder().key(LOCAL_COMPONENT).value("archiver");
    BinaryAnnotation archiver1 = component.endpoint(service1).build();
    BinaryAnnotation archiver2 = component.endpoint(service2).build();
    BinaryAnnotation archiver3 = component.endpoint(service3).build();
    Span targz = Span.builder().traceId(1L).id(1L).name("targz").timestamp(today * 1000 + 100L).duration(200L).addBinaryAnnotation(archiver1).build();
    Span tar = Span.builder().traceId(1L).id(2L).parentId(1L).name("tar").timestamp(today * 1000 + 200L).duration(150L).addBinaryAnnotation(archiver2).build();
    Span gz = Span.builder().traceId(1L).id(3L).parentId(1L).name("gz").timestamp(today * 1000 + 250L).duration(50L).addBinaryAnnotation(archiver3).build();
    Span zip = Span.builder().traceId(3L).id(3L).name("zip").timestamp(today * 1000 + 130L).duration(50L).addBinaryAnnotation(archiver2).build();
    List<Span> trace1 = asList(targz, tar, gz);
    List<Span> trace2 = asList(targz.toBuilder().traceId(2L).timestamp(today * 1000 + 110L).binaryAnnotations(asList(archiver3)).build(), tar.toBuilder().traceId(2L).timestamp(today * 1000 + 210L).binaryAnnotations(asList(archiver2)).build(), gz.toBuilder().traceId(2L).timestamp(today * 1000 + 260L).binaryAnnotations(asList(archiver1)).build());
    List<Span> trace3 = asList(zip);
    accept(trace1.toArray(new Span[0]));
    accept(trace2.toArray(new Span[0]));
    accept(trace3.toArray(new Span[0]));
    // 12hrs, instead of 7days
    long lookback = 12L * 60 * 60 * 1000;
    // greater than all timestamps above
    long endTs = today + 1;
    QueryRequest.Builder q = QueryRequest.builder().serviceName("service1").lookback(lookback).endTs(endTs);
    // Min duration is inclusive and is applied by service.
    assertThat(store().getTraces(q.serviceName("service1").minDuration(targz.duration).build())).containsExactly(trace1);
    assertThat(store().getTraces(q.serviceName("service3").minDuration(targz.duration).build())).containsExactly(trace2);
    // Duration bounds aren't limited to root spans: they apply to all spans by service in a trace
    assertThat(store().getTraces(q.serviceName("service2").minDuration(zip.duration).maxDuration(tar.duration).build())).containsExactly(trace3, trace2, // service2 is in the middle of trace1 and 2, but root of trace3
    trace1);
    // Span name should apply to the duration filter
    assertThat(store().getTraces(q.serviceName("service2").spanName("zip").maxDuration(zip.duration).build())).containsExactly(trace3);
    // Max duration should filter our longer spans from the same service
    assertThat(store().getTraces(q.serviceName("service2").minDuration(gz.duration).maxDuration(zip.duration).build())).containsExactly(trace3);
}
Also used : BinaryAnnotation(zipkin.BinaryAnnotation) Endpoint(zipkin.Endpoint) Span(zipkin.Span) Test(org.junit.Test)

Example 34 with Span

use of zipkin.Span in project zipkin by openzipkin.

the class SpanStoreTest method getTraces_differentiateOnServiceName.

/**
   * This test makes sure that annotation queries pay attention to which host logged an annotation.
   */
@Test
public void getTraces_differentiateOnServiceName() {
    Span trace1 = Span.builder().traceId(1).name("get").id(1).timestamp((today + 1) * 1000).addAnnotation(Annotation.create((today + 1) * 1000, CLIENT_SEND, WEB_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, SERVER_RECV, APP_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, SERVER_SEND, APP_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, CLIENT_RECV, WEB_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, "web", WEB_ENDPOINT)).addBinaryAnnotation(BinaryAnnotation.create("local", "web", WEB_ENDPOINT)).addBinaryAnnotation(BinaryAnnotation.create("web-b", "web", WEB_ENDPOINT)).build();
    Span trace2 = Span.builder().traceId(2).name("get").id(2).timestamp((today + 2) * 1000).addAnnotation(Annotation.create((today + 1) * 1000, CLIENT_SEND, APP_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, SERVER_RECV, WEB_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, SERVER_SEND, WEB_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, CLIENT_RECV, APP_ENDPOINT)).addAnnotation(Annotation.create((today + 1) * 1000, "app", APP_ENDPOINT)).addBinaryAnnotation(BinaryAnnotation.create("local", "app", APP_ENDPOINT)).addBinaryAnnotation(BinaryAnnotation.create("app-b", "app", APP_ENDPOINT)).build();
    accept(trace1, trace2);
    assertThat(store().getTraces(QueryRequest.builder().build())).containsExactly(asList(trace2), asList(trace1));
    // We only return traces where the service specified caused the annotation queried.
    assertThat(store().getTraces(QueryRequest.builder().serviceName("web").addAnnotation("web").build())).containsExactly(asList(trace1));
    assertThat(store().getTraces(QueryRequest.builder().serviceName("app").addAnnotation("web").build())).isEmpty();
    assertThat(store().getTraces(QueryRequest.builder().serviceName("app").addAnnotation("app").build())).containsExactly(asList(trace2));
    assertThat(store().getTraces(QueryRequest.builder().serviceName("web").addAnnotation("app").build())).isEmpty();
    // Binary annotations are not returned for annotation queries
    assertThat(store().getTraces(QueryRequest.builder().serviceName("web").addAnnotation("web-b").build())).isEmpty();
    assertThat(store().getTraces(QueryRequest.builder().serviceName("app").addAnnotation("web-b").build())).isEmpty();
    assertThat(store().getTraces(QueryRequest.builder().serviceName("app").addAnnotation("app-b").build())).isEmpty();
    assertThat(store().getTraces(QueryRequest.builder().serviceName("web").addAnnotation("app-b").build())).isEmpty();
    // We only return traces where the service specified caused the binary value queried.
    assertThat(store().getTraces(QueryRequest.builder().serviceName("web").addBinaryAnnotation("local", "web").build())).containsExactly(asList(trace1));
    assertThat(store().getTraces(QueryRequest.builder().serviceName("app").addBinaryAnnotation("local", "web").build())).isEmpty();
    assertThat(store().getTraces(QueryRequest.builder().serviceName("app").addBinaryAnnotation("local", "app").build())).containsExactly(asList(trace2));
    assertThat(store().getTraces(QueryRequest.builder().serviceName("web").addBinaryAnnotation("local", "app").build())).isEmpty();
}
Also used : Span(zipkin.Span) Test(org.junit.Test)

Example 35 with Span

use of zipkin.Span in project zipkin by openzipkin.

the class SpanStoreTest method rawTrace_doesntPerformQueryTimeAdjustment.

// This supports the "raw trace" feature, which skips application-level data cleaning
@Test
public void rawTrace_doesntPerformQueryTimeAdjustment() {
    Endpoint producer = Endpoint.create("producer", 192 << 24 | 168 << 16 | 1);
    Annotation ms = Annotation.create((today + 95) * 1000, "ms", producer);
    Endpoint consumer = Endpoint.create("consumer", 192 << 24 | 168 << 16 | 2);
    Annotation mr = Annotation.create((today + 100) * 1000, "mr", consumer);
    Span span = Span.builder().traceId(1).name("message").id(666).build();
    // Simulate instrumentation that sends annotations one at-a-time.
    // This should prevent the collection tier from being able to calculate duration.
    accept(span.toBuilder().addAnnotation(ms).build());
    accept(span.toBuilder().addAnnotation(mr).build());
    // Normally, span store implementations will merge spans by id and add duration by query time
    assertThat(store().getTrace(span1.traceIdHigh, span.traceId)).containsExactly(span.toBuilder().timestamp(ms.timestamp).duration(mr.timestamp - ms.timestamp).annotations(asList(ms, mr)).build());
    // Since a collector never saw both sides of the span, we'd not see duration in the raw trace.
    for (Span raw : store().getRawTrace(span1.traceIdHigh, span.traceId)) {
        assertThat(raw.timestamp).isNull();
        assertThat(raw.duration).isNull();
    }
}
Also used : Endpoint(zipkin.Endpoint) Span(zipkin.Span) Annotation(zipkin.Annotation) BinaryAnnotation(zipkin.BinaryAnnotation) Test(org.junit.Test)

Aggregations

Span (zipkin.Span)104 Test (org.junit.Test)84 Endpoint (zipkin.Endpoint)21 BinaryAnnotation (zipkin.BinaryAnnotation)12 ArrayList (java.util.ArrayList)11 Annotation (zipkin.Annotation)10 CodecTest (zipkin.CodecTest)9 CorrectForClockSkew.isLocalSpan (zipkin.internal.CorrectForClockSkew.isLocalSpan)9 ByteBuffer (java.nio.ByteBuffer)8 List (java.util.List)8 Buffer (okio.Buffer)8 LinkedHashMap (java.util.LinkedHashMap)6 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)5 ImmutableList (com.google.common.collect.ImmutableList)4 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)4 LinkedList (java.util.LinkedList)4 Constants (zipkin.Constants)4 ImmutableSet (com.google.common.collect.ImmutableSet)3 IOException (java.io.IOException)3 Arrays.asList (java.util.Arrays.asList)3