Search in sources :

Example 66 with Kind

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

the class BulkIndexWriter method write.

/**
 * In order to allow systems like Kibana to search by timestamp, we add a field "timestamp_millis"
 * when storing. The cheapest way to do this without changing the codec is prefixing it to the
 * json. For example. {"traceId":"... becomes {"timestamp_millis":12345,"traceId":"...
 *
 * <p>Tags are stored as a dictionary. Since some tag names will include inconsistent number of
 * dots (ex "error" and perhaps "error.message"), we cannot index them naturally with
 * elasticsearch. Instead, we add an index-only (non-source) field of {@code _q} which includes
 * valid search queries. For example, the tag {@code error -> 500} results in {@code
 * "_q":["error", "error=500"]}. This matches the input query syntax, and can be checked manually
 * with curl.
 *
 * <p>Ex {@code curl -s localhost:9200/zipkin:span-2017-08-11/_search?q=_q:error=500}
 *
 * @param searchEnabled encodes timestamp_millis and _q when non-empty
 */
static String write(Span span, boolean searchEnabled, ByteBufOutputStream sink) {
    int startIndex = sink.buffer().writerIndex();
    try (JsonGenerator writer = JsonSerializers.jsonGenerator(sink)) {
        writer.writeStartObject();
        if (searchEnabled)
            addSearchFields(span, writer);
        writer.writeStringField("traceId", span.traceId());
        if (span.parentId() != null)
            writer.writeStringField("parentId", span.parentId());
        writer.writeStringField("id", span.id());
        if (span.kind() != null)
            writer.writeStringField("kind", span.kind().toString());
        if (span.name() != null)
            writer.writeStringField("name", span.name());
        if (span.timestampAsLong() != 0L) {
            writer.writeNumberField("timestamp", span.timestampAsLong());
        }
        if (span.durationAsLong() != 0L)
            writer.writeNumberField("duration", span.durationAsLong());
        if (span.localEndpoint() != null && !EMPTY_ENDPOINT.equals(span.localEndpoint())) {
            writer.writeFieldName("localEndpoint");
            write(span.localEndpoint(), writer);
        }
        if (span.remoteEndpoint() != null && !EMPTY_ENDPOINT.equals(span.remoteEndpoint())) {
            writer.writeFieldName("remoteEndpoint");
            write(span.remoteEndpoint(), writer);
        }
        if (!span.annotations().isEmpty()) {
            writer.writeArrayFieldStart("annotations");
            for (int i = 0, length = span.annotations().size(); i < length; ) {
                write(span.annotations().get(i++), writer);
            }
            writer.writeEndArray();
        }
        if (!span.tags().isEmpty()) {
            writer.writeObjectFieldStart("tags");
            Iterator<Map.Entry<String, String>> tags = span.tags().entrySet().iterator();
            while (tags.hasNext()) write(tags.next(), writer);
            writer.writeEndObject();
        }
        if (Boolean.TRUE.equals(span.debug()))
            writer.writeBooleanField("debug", true);
        if (Boolean.TRUE.equals(span.shared()))
            writer.writeBooleanField("shared", true);
        writer.writeEndObject();
    } catch (IOException e) {
        // No I/O writing to a Buffer.
        throw new AssertionError(e);
    }
    // get a slice representing the document we just wrote so that we can make a content hash
    ByteBuf slice = sink.buffer().slice(startIndex, sink.buffer().writerIndex() - startIndex);
    return span.traceId() + '-' + md5(slice);
}
Also used : JsonGenerator(com.fasterxml.jackson.core.JsonGenerator) IOException(java.io.IOException) ByteBuf(io.netty.buffer.ByteBuf) Endpoint(zipkin2.Endpoint)

Example 67 with Kind

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

the class V2SpanWriter method write.

@Override
public void write(Span value, WriteBuffer b) {
    b.writeAscii("{\"traceId\":\"");
    b.writeAscii(value.traceId());
    b.writeByte('"');
    if (value.parentId() != null) {
        b.writeAscii(",\"parentId\":\"");
        b.writeAscii(value.parentId());
        b.writeByte('"');
    }
    b.writeAscii(",\"id\":\"");
    b.writeAscii(value.id());
    b.writeByte('"');
    if (value.kind() != null) {
        b.writeAscii(",\"kind\":\"");
        b.writeAscii(value.kind().toString());
        b.writeByte('"');
    }
    if (value.name() != null) {
        b.writeAscii(",\"name\":\"");
        b.writeUtf8(jsonEscape(value.name()));
        b.writeByte('"');
    }
    if (value.timestampAsLong() != 0L) {
        b.writeAscii(",\"timestamp\":");
        b.writeAscii(value.timestampAsLong());
    }
    if (value.durationAsLong() != 0L) {
        b.writeAscii(",\"duration\":");
        b.writeAscii(value.durationAsLong());
    }
    if (value.localEndpoint() != null) {
        b.writeAscii(",\"localEndpoint\":");
        writeEndpoint(value.localEndpoint(), b, false);
    }
    if (value.remoteEndpoint() != null) {
        b.writeAscii(",\"remoteEndpoint\":");
        writeEndpoint(value.remoteEndpoint(), b, false);
    }
    if (!value.annotations().isEmpty()) {
        b.writeAscii(",\"annotations\":");
        b.writeByte('[');
        for (int i = 0, length = value.annotations().size(); i < length; ) {
            Annotation a = value.annotations().get(i++);
            writeAnnotation(a.timestamp(), a.value(), null, b);
            if (i < length)
                b.writeByte(',');
        }
        b.writeByte(']');
    }
    if (!value.tags().isEmpty()) {
        b.writeAscii(",\"tags\":{");
        Iterator<Map.Entry<String, String>> i = value.tags().entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry<String, String> entry = i.next();
            b.writeByte('"');
            b.writeUtf8(jsonEscape(entry.getKey()));
            b.writeAscii("\":\"");
            b.writeUtf8(jsonEscape(entry.getValue()));
            b.writeByte('"');
            if (i.hasNext())
                b.writeByte(',');
        }
        b.writeByte('}');
    }
    if (Boolean.TRUE.equals(value.debug())) {
        b.writeAscii(",\"debug\":true");
    }
    if (Boolean.TRUE.equals(value.shared())) {
        b.writeAscii(",\"shared\":true");
    }
    b.writeByte('}');
}
Also used : Map(java.util.Map) Endpoint(zipkin2.Endpoint) Annotation(zipkin2.Annotation)

Example 68 with Kind

use of zipkin2.Span.Kind 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 69 with Kind

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

the class SpanConverterTest method producerAndConsumer_loopback_shared.

/**
 * shared v1 IDs for messaging spans isn't supported, but shouldn't break
 */
@Test
public void producerAndConsumer_loopback_shared() {
    V1Span v1 = V1Span.newBuilder().traceId(1).parentId(2).id(3).name("message").addAnnotation(1472470996199000L, "ms", FRONTEND).addAnnotation(1472470996238000L, "ws", FRONTEND).addAnnotation(1472470996403000L, "wr", FRONTEND).addAnnotation(1472470996406000L, "mr", FRONTEND).build();
    Span.Builder newBuilder = Span.newBuilder().traceId("1").parentId("2").id("3").name("message");
    Span producer = newBuilder.clone().kind(Kind.PRODUCER).localEndpoint(FRONTEND).timestamp(1472470996199000L).duration(1472470996238000L - 1472470996199000L).build();
    Span consumer = newBuilder.clone().kind(Kind.CONSUMER).shared(true).localEndpoint(FRONTEND).timestamp(1472470996403000L).duration(1472470996406000L - 1472470996403000L).build();
    assertThat(v1SpanConverter.convert(v1)).containsExactly(producer, consumer);
}
Also used : Span(zipkin2.Span) Test(org.junit.Test)

Example 70 with Kind

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

the class SpanConverterTest method lateRemoteEndpoint_cr.

@Test
public void lateRemoteEndpoint_cr() {
    Span v2 = Span.newBuilder().traceId("1").parentId("2").id("3").name("get").kind(Kind.CLIENT).localEndpoint(FRONTEND).remoteEndpoint(BACKEND).addAnnotation(1472470996199000L, "cr").build();
    V1Span v1 = V1Span.newBuilder().traceId(1L).parentId(2L).id(3L).name("get").addAnnotation(1472470996199000L, "cr", FRONTEND).addBinaryAnnotation("sa", BACKEND).build();
    assertThat(v2SpanConverter.convert(v2)).usingRecursiveComparison().isEqualTo(v1);
    assertThat(v1SpanConverter.convert(v1)).containsExactly(v2);
}
Also used : Span(zipkin2.Span) Test(org.junit.Test)

Aggregations

Span (zipkin2.Span)77 Test (org.junit.Test)54 Endpoint (zipkin2.Endpoint)28 Test (org.junit.jupiter.api.Test)17 V1Span (zipkin2.v1.V1Span)10 TraceSpan (com.google.devtools.cloudtrace.v1.TraceSpan)8 SpanSampler (com.wavefront.agent.sampler.SpanSampler)6 ByteBuf (io.netty.buffer.ByteBuf)6 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)6 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)6 IOException (java.io.IOException)6 Map (java.util.Map)6 Span (wavefront.report.Span)6 NoopHealthCheckManager (com.wavefront.agent.channel.NoopHealthCheckManager)5 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)5 TestObjects.newClientSpan (zipkin2.TestObjects.newClientSpan)5 Trace (com.google.devtools.cloudtrace.v1.Trace)4 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)4 Annotation (wavefront.report.Annotation)4 Annotation (zipkin2.Annotation)3