Search in sources :

Example 1 with Annotation

use of zipkin.Annotation in project zipkin by openzipkin.

the class ApplyTimestampAndDuration method apply.

/**
   * For RPC two-way spans, the duration between "cs" and "cr" is authoritative. RPC one-way spans
   * lack a response, so the duration is between "cs" and "sr". We special-case this to avoid
   * setting incorrect duration when there's skew between the client and the server.
   *
   * <p>Note: this should only be used for query, not storage commands!
   */
public static Span apply(Span span) {
    // Don't overwrite authoritatively set timestamp and duration!
    if (span.timestamp != null && span.duration != null) {
        return span;
    }
    // backfill timestamp.
    if (span.annotations.size() < 2) {
        if (span.timestamp != null)
            return span;
        Long guess = guessTimestamp(span);
        if (guess == null)
            return span;
        return span.toBuilder().timestamp(guess).build();
    }
    // Prefer RPC one-way (cs -> sr) vs arbitrary annotations.
    Long first = span.annotations.get(0).timestamp;
    Long last = span.annotations.get(span.annotations.size() - 1).timestamp;
    for (int i = 0, length = span.annotations.size(); i < length; i++) {
        Annotation annotation = span.annotations.get(i);
        if (annotation.value.equals(Constants.CLIENT_SEND)) {
            first = annotation.timestamp;
        } else if (annotation.value.equals(Constants.CLIENT_RECV)) {
            last = annotation.timestamp;
        }
    }
    long ts = span.timestamp != null ? span.timestamp : first;
    Long dur = span.duration != null ? span.duration : last.equals(first) ? null : last - first;
    return span.toBuilder().timestamp(ts).duration(dur).build();
}
Also used : Annotation(zipkin.Annotation)

Example 2 with Annotation

use of zipkin.Annotation in project zipkin by openzipkin.

the class ApplyTimestampAndDuration method guessTimestamp.

/**
   * Instrumentation should set {@link Span#timestamp} when recording a span so that guess-work
   * isn't needed. Since a lot of instrumentation don't, we have to make some guesses.
   *
   * <pre><ul>
   *   <li>If there is a {@link Constants#CLIENT_SEND}, use that</li>
   *   <li>Fall back to {@link Constants#SERVER_RECV}, if a root span</li>
   *   <li>Otherwise, return null</li>
   * </ul></pre>
   */
public static Long guessTimestamp(Span span) {
    if (span.timestamp != null || span.annotations.isEmpty())
        return span.timestamp;
    boolean isRoot = span.parentId == null;
    Long rootServerRecv = null;
    for (int i = 0, length = span.annotations.size(); i < length; i++) {
        Annotation annotation = span.annotations.get(i);
        if (annotation.value.equals(Constants.CLIENT_SEND)) {
            return annotation.timestamp;
        } else if (annotation.value.equals(Constants.SERVER_RECV) && isRoot) {
            rootServerRecv = annotation.timestamp;
        }
    }
    return rootServerRecv;
}
Also used : Annotation(zipkin.Annotation)

Example 3 with Annotation

use of zipkin.Annotation 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 4 with Annotation

use of zipkin.Annotation 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)

Example 5 with Annotation

use of zipkin.Annotation in project zipkin by openzipkin.

the class ZipkinServerTest method readsBackSpanName.

@Test
public void readsBackSpanName() throws Exception {
    String service = "web";
    Endpoint endpoint = Endpoint.create(service, 127 << 24 | 1, 80);
    Annotation ann = Annotation.create(System.currentTimeMillis() * 1000, SERVER_RECV, endpoint);
    Span span = Span.builder().id(1L).traceId(1L).name("get").addAnnotation(ann).build();
    // write the span to the server
    performAsync(post("/api/v1/spans").content(Codec.JSON.writeSpans(asList(span)))).andExpect(status().isAccepted());
    // sleep as the the storage operation is async
    Thread.sleep(1000);
    // read back the span name, given its service
    mockMvc.perform(get("/api/v1/spans?serviceName=" + service)).andExpect(status().isOk()).andExpect(content().string("[\"" + span.name + "\"]"));
}
Also used : Endpoint(zipkin.Endpoint) Span(zipkin.Span) Annotation(zipkin.Annotation) Test(org.junit.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest)

Aggregations

Annotation (zipkin.Annotation)17 BinaryAnnotation (zipkin.BinaryAnnotation)14 Span (zipkin.Span)7 Test (org.junit.Test)6 ArrayList (java.util.ArrayList)5 Endpoint (zipkin.Endpoint)5 LinkedHashSet (java.util.LinkedHashSet)3 Span (com.uber.jaeger.Span)2 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 BoundStatement (com.datastax.driver.core.BoundStatement)1 SpanContext (com.uber.jaeger.SpanContext)1 Connection (java.sql.Connection)1 SQLException (java.sql.SQLException)1 HashSet (java.util.HashSet)1 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1 TreeSet (java.util.TreeSet)1 UUID (java.util.UUID)1 DSLContext (org.jooq.DSLContext)1