Search in sources :

Example 41 with SERVER

use of zipkin2.Span.Kind.SERVER in project zipkin by openzipkin.

the class Trace method merge.

/*
   * Spans can be sent in multiple parts. Also client and server spans can share the same ID. This
   * merges both scenarios.
   */
public static List<Span> merge(List<Span> spans) {
    int length = spans.size();
    if (length <= 1)
        return spans;
    List<Span> result = new ArrayList<Span>(spans);
    Collections.sort(result, CLEANUP_COMPARATOR);
    // Let's cleanup any spans and pick the longest ID
    String traceId = result.get(0).traceId();
    for (int i = 1; i < length; i++) {
        String nextTraceId = result.get(i).traceId();
        if (traceId.length() != 32)
            traceId = nextTraceId;
    }
    // Now start any fixes or merging
    Span last = null;
    for (int i = 0; i < length; i++) {
        Span span = result.get(i);
        // String previousId = last.id();
        boolean spanShared = Boolean.TRUE.equals(span.shared());
        // Choose the longest trace ID
        Span.Builder replacement = null;
        if (span.traceId().length() != traceId.length()) {
            replacement = span.toBuilder().traceId(traceId);
        }
        EndpointTracker localEndpoint = null;
        while (i + 1 < length) {
            Span next = result.get(i + 1);
            String nextId = next.id();
            if (!nextId.equals(span.id()))
                break;
            if (localEndpoint == null) {
                localEndpoint = new EndpointTracker();
                localEndpoint.tryMerge(span.localEndpoint());
            }
            // This cautiously merges with the next span, if we think it was sent in multiple pieces.
            boolean nextShared = Boolean.TRUE.equals(next.shared());
            if (spanShared == nextShared && localEndpoint.tryMerge(next.localEndpoint())) {
                if (replacement == null)
                    replacement = span.toBuilder();
                replacement.merge(next);
                // remove the merged element
                length--;
                result.remove(i + 1);
                continue;
            }
            break;
        }
        // have the entire trace, and it is ordered client-first, we can correct a missing shared flag.
        if (last != null && last.id().equals(span.id())) {
            // Backfill missing shared flag as some instrumentation doesn't add it
            if (last.kind() == Span.Kind.CLIENT && span.kind() == Span.Kind.SERVER && !spanShared) {
                spanShared = true;
                if (replacement == null)
                    replacement = span.toBuilder();
                replacement.shared(true);
            }
            if (spanShared && span.parentId() == null && last.parentId() != null) {
                // handle a shared RPC server span that wasn't propagated its parent span ID
                if (replacement == null)
                    replacement = span.toBuilder();
                replacement.parentId(last.parentId());
            }
        }
        if (replacement != null) {
            span = replacement.build();
            result.set(i, span);
        }
        last = span;
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) Span(zipkin2.Span) Endpoint(zipkin2.Endpoint)

Example 42 with SERVER

use of zipkin2.Span.Kind.SERVER in project zipkin by openzipkin.

the class DependencyLinker method putTrace.

/**
 * All {@code spans} must have the same trace id.
 */
public DependencyLinker putTrace(List<Span> spans) {
    if (spans.isEmpty())
        return this;
    SpanNode traceTree = builder.build(spans);
    if (logger.isLoggable(FINE))
        logger.fine("traversing trace tree, breadth-first");
    for (Iterator<SpanNode> i = traceTree.traverse(); i.hasNext(); ) {
        SpanNode current = i.next();
        Span currentSpan = current.span();
        if (logger.isLoggable(FINE)) {
            logger.fine("processing " + currentSpan);
        }
        Kind kind = currentSpan.kind();
        // spans, we proceed to use the name the client chose.
        if (Kind.CLIENT.equals(kind) && !current.children().isEmpty()) {
            continue;
        }
        String serviceName = currentSpan.localServiceName();
        String remoteServiceName = currentSpan.remoteServiceName();
        if (kind == null) {
            // Treat unknown type of span as a client span if we know both sides
            if (serviceName != null && remoteServiceName != null) {
                kind = Kind.CLIENT;
            } else {
                logger.fine("non remote span; skipping");
                continue;
            }
        }
        String child;
        String parent;
        switch(kind) {
            case SERVER:
            case CONSUMER:
                child = serviceName;
                parent = remoteServiceName;
                if (current == traceTree) {
                    // we are the root-most span.
                    if (parent == null) {
                        logger.fine("root's client is unknown; skipping");
                        continue;
                    }
                }
                break;
            case CLIENT:
            case PRODUCER:
                parent = serviceName;
                child = remoteServiceName;
                break;
            default:
                logger.fine("unknown kind; skipping");
                continue;
        }
        boolean isError = currentSpan.tags().containsKey("error");
        if (kind == Kind.PRODUCER || kind == Kind.CONSUMER) {
            if (parent == null || child == null) {
                logger.fine("cannot link messaging span to its broker; skipping");
            } else {
                addLink(parent, child, isError);
            }
            continue;
        }
        // Local spans may be between the current node and its remote parent
        Span remoteAncestor = firstRemoteAncestor(current);
        String remoteAncestorName;
        if (remoteAncestor != null && (remoteAncestorName = remoteAncestor.localServiceName()) != null) {
            // Check for this and backfill a link from the nearest remote to that service as necessary.
            if (kind == Kind.CLIENT && serviceName != null && !remoteAncestorName.equals(serviceName)) {
                logger.fine("detected missing link to client span");
                // we don't know if there's an error here
                addLink(remoteAncestorName, serviceName, false);
            }
            if (kind == Kind.SERVER || parent == null)
                parent = remoteAncestorName;
            // client, we need to check it for errors.
            if (!isError && Kind.CLIENT.equals(remoteAncestor.kind()) && currentSpan.parentId() != null && currentSpan.parentId().equals(remoteAncestor.id())) {
                isError = remoteAncestor.tags().containsKey("error");
            }
        }
        if (parent == null || child == null) {
            logger.fine("cannot find remote ancestor; skipping");
            continue;
        }
        addLink(parent, child, isError);
    }
    return this;
}
Also used : Kind(zipkin2.Span.Kind) Span(zipkin2.Span)

Example 43 with SERVER

use of zipkin2.Span.Kind.SERVER in project zipkin by openzipkin.

the class SpanConverterTest method redundantAddressAnnotations_client.

/**
 * Intentionally create service loopback endpoints as dependency linker can correct it later if
 * incorrect, provided the server is instrumented.
 */
@Test
public void redundantAddressAnnotations_client() {
    Span v2 = Span.newBuilder().traceId("1").parentId("2").id("3").kind(Kind.CLIENT).name("get").localEndpoint(FRONTEND).remoteEndpoint(FRONTEND).timestamp(1472470996199000L).duration(207000L).build();
    V1Span v1 = V1Span.newBuilder().traceId(1L).parentId(2L).id(3L).name("get").timestamp(1472470996199000L).duration(207000L).addAnnotation(1472470996199000L, "cs", FRONTEND).addAnnotation(1472470996406000L, "cr", FRONTEND).addBinaryAnnotation("ca", FRONTEND).addBinaryAnnotation("sa", FRONTEND).build();
    assertThat(v1SpanConverter.convert(v1)).containsExactly(v2);
}
Also used : Span(zipkin2.Span) Test(org.junit.Test)

Example 44 with SERVER

use of zipkin2.Span.Kind.SERVER in project zipkin by openzipkin.

the class DependencyLinkV2SpanIteratorTest method specialCasesFinagleLocalSocketLabeling_server.

@Test
public void specialCasesFinagleLocalSocketLabeling_server() {
    DependencyLinkV2SpanIterator iterator = iterator(newRecord().values(traceIdHigh, traceId, parentId, spanId, "ca", TYPE_BOOLEAN, "service"), newRecord().values(traceIdHigh, traceId, parentId, spanId, "sa", TYPE_BOOLEAN, "service"), newRecord().values(traceIdHigh, traceId, parentId, spanId, "sr", -1, "service"));
    Span span = iterator.next();
    // When there is an "sr" annotation, we know it is a server
    assertThat(span.kind()).isEqualTo(Span.Kind.SERVER);
    assertThat(span.localServiceName()).isEqualTo("service");
    assertThat(span.remoteEndpoint()).isNull();
}
Also used : Span(zipkin2.Span) Test(org.junit.Test)

Example 45 with SERVER

use of zipkin2.Span.Kind.SERVER in project zipkin by openzipkin.

the class ITDependencies method getDependencies_linksMixedTraceId.

/**
 * This tests that dependency linking ignores the high-bits of the trace ID when grouping spans
 * for dependency links. This allows environments with 64-bit instrumentation to participate in
 * the same trace as 128-bit instrumentation.
 */
@Test
protected void getDependencies_linksMixedTraceId(TestInfo testInfo) throws Exception {
    String testSuffix = testSuffix(testInfo);
    String traceId = newTraceId();
    Endpoint frontend = suffixServiceName(TestObjects.FRONTEND, testSuffix);
    Endpoint backend = suffixServiceName(TestObjects.BACKEND, testSuffix);
    List<Span> mixedTrace = asList(Span.newBuilder().traceId(traceId).id("1").name("get").kind(Kind.SERVER).timestamp(TODAY * 1000L).duration(350 * 1000L).localEndpoint(frontend).build(), // the server dropped traceIdHigh
    Span.newBuilder().traceId(traceId.substring(16)).parentId("1").id("2").name("get").kind(Kind.SERVER).shared(true).timestamp((TODAY + 100) * 1000L).duration(250 * 1000L).localEndpoint(backend).build(), Span.newBuilder().traceId(traceId).parentId("1").id("2").kind(Kind.CLIENT).timestamp((TODAY + 50) * 1000L).duration(300 * 1000L).localEndpoint(frontend).build());
    processDependencies(mixedTrace);
    assertThat(store().getDependencies(endTs(mixedTrace), DAY).execute()).containsOnly(DependencyLink.newBuilder().parent(frontend.serviceName()).child(backend.serviceName()).callCount(1).build());
}
Also used : Endpoint(zipkin2.Endpoint) Span(zipkin2.Span) V1Span(zipkin2.v1.V1Span) Test(org.junit.jupiter.api.Test)

Aggregations

Span (zipkin2.Span)36 Test (org.junit.Test)31 Endpoint (zipkin2.Endpoint)17 Test (org.junit.jupiter.api.Test)9 TraceSpan (com.google.devtools.cloudtrace.v1.TraceSpan)7 Trace (com.google.devtools.cloudtrace.v1.Trace)5 NoopHealthCheckManager (com.wavefront.agent.channel.NoopHealthCheckManager)5 SpanSampler (com.wavefront.agent.sampler.SpanSampler)5 ByteBuf (io.netty.buffer.ByteBuf)5 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)5 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)5 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)5 Span (wavefront.report.Span)5 Task (io.crnk.monitor.brave.mock.models.Task)4 TestObjects.newClientSpan (zipkin2.TestObjects.newClientSpan)4 SpanBytesEncoder (zipkin2.codec.SpanBytesEncoder)4 RateSampler (com.wavefront.sdk.entities.tracing.sampling.RateSampler)3 Annotation (wavefront.report.Annotation)3 ElasticsearchStorage (zipkin2.elasticsearch.ElasticsearchStorage)3 V1Span (zipkin2.v1.V1Span)3