Search in sources :

Example 6 with BinaryAnnotation

use of zipkin.BinaryAnnotation in project zipkin by openzipkin.

the class CassandraSpanConsumer method storeSpan.

/**
   * Store the span in the underlying storage for later retrieval.
   */
ListenableFuture<?> storeSpan(Span span, TraceIdUDT traceId, boolean isServerRecvSpan, Long timestamp) {
    try {
        if ((null == timestamp || 0 == timestamp) && !isServerRecvSpan && metadata.compactionClass.contains("TimeWindowCompactionStrategy")) {
            LOG.warn("Span {} in trace {} had no timestamp. " + "If this happens a lot consider switching back to SizeTieredCompactionStrategy for " + "{}.traces", span.id, span.traceId, session.getLoggedKeyspace());
        }
        List<AnnotationUDT> annotations = new ArrayList<>(span.annotations.size());
        for (Annotation annotation : span.annotations) {
            annotations.add(new AnnotationUDT(annotation));
        }
        List<BinaryAnnotationUDT> binaryAnnotations = new ArrayList<>(span.binaryAnnotations.size());
        for (BinaryAnnotation annotation : span.binaryAnnotations) {
            binaryAnnotations.add(new BinaryAnnotationUDT(annotation));
        }
        Set<String> annotationKeys = CassandraUtil.annotationKeys(span);
        if (!strictTraceId && traceId.getHigh() != 0L) {
            storeSpan(span, new TraceIdUDT(0L, traceId.getLow()), isServerRecvSpan, timestamp);
        }
        BoundStatement bound = bindWithName(insertSpan, "insert-span").set("trace_id", traceId, TraceIdUDT.class).setUUID("ts_uuid", new UUID(UUIDs.startOf(null != timestamp ? (timestamp / 1000) : 0).getMostSignificantBits(), UUIDs.random().getLeastSignificantBits())).setLong("id", span.id).setString("span_name", span.name).setList("annotations", annotations).setList("binary_annotations", binaryAnnotations).setString("all_annotations", Joiner.on(',').join(annotationKeys));
        if (null != span.timestamp) {
            bound = bound.setLong("ts", span.timestamp);
        }
        if (null != span.duration) {
            bound = bound.setLong("duration", span.duration);
        }
        if (null != span.parentId) {
            bound = bound.setLong("parent_id", span.parentId);
        }
        return session.executeAsync(bound);
    } catch (RuntimeException ex) {
        return Futures.immediateFailedFuture(ex);
    }
}
Also used : ArrayList(java.util.ArrayList) BinaryAnnotationUDT(zipkin.storage.cassandra3.Schema.BinaryAnnotationUDT) AnnotationUDT(zipkin.storage.cassandra3.Schema.AnnotationUDT) Annotation(zipkin.Annotation) BinaryAnnotation(zipkin.BinaryAnnotation) BinaryAnnotation(zipkin.BinaryAnnotation) BinaryAnnotationUDT(zipkin.storage.cassandra3.Schema.BinaryAnnotationUDT) UUID(java.util.UUID) BoundStatement(com.datastax.driver.core.BoundStatement) TraceIdUDT(zipkin.storage.cassandra3.Schema.TraceIdUDT)

Example 7 with BinaryAnnotation

use of zipkin.BinaryAnnotation in project zipkin by openzipkin.

the class CassandraUtil method annotationKeys.

/**
   * Returns keys that concatenate the serviceName associated with an annotation or a binary
   * annotation.
   *
   * <p>Note: Annotations are delimited with colons while Binary Annotations are delimited with
   * semi-colons. This is because the returned keys are joined on comma and queried with LIKE. For
   * example, a span with the annotation "foo" and a binary annotation "bar" -> "baz" would end up
   * in a cell "service:foo,service:bar:baz". A query for the annotation "bar" would satisfy as
   * "service:bar" is a substring of that cell. This is imprecise. By joining binary annotations on
   * semicolon, this mismatch cannot happen.
   *
   * <p>Note: in the case of binary annotations, only string types are returned, as that's the only
   * queryable type, per {@link QueryRequest#binaryAnnotations}.
   *
   * @see QueryRequest#annotations
   * @see QueryRequest#binaryAnnotations
   */
static Set<String> annotationKeys(Span span) {
    Set<String> annotationKeys = new LinkedHashSet<>();
    for (Annotation a : span.annotations) {
        // don't index core annotations as they aren't queryable
        if (Constants.CORE_ANNOTATIONS.contains(a.value))
            continue;
        if (a.endpoint != null && !a.endpoint.serviceName.isEmpty()) {
            annotationKeys.add(a.endpoint.serviceName + ":" + a.value);
        }
    }
    for (BinaryAnnotation b : span.binaryAnnotations) {
        if (b.type != BinaryAnnotation.Type.STRING || b.endpoint == null || b.endpoint.serviceName.isEmpty() || b.value.length > LONGEST_VALUE_TO_INDEX * 4) {
            // UTF_8 is up to 4bytes/char
            continue;
        }
        String value = new String(b.value, UTF_8);
        if (value.length() > LONGEST_VALUE_TO_INDEX)
            continue;
        annotationKeys.add(b.endpoint.serviceName + ";" + b.key + ";" + new String(b.value, UTF_8));
    }
    return annotationKeys;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) BinaryAnnotation(zipkin.BinaryAnnotation) Annotation(zipkin.Annotation) BinaryAnnotation(zipkin.BinaryAnnotation)

Example 8 with BinaryAnnotation

use of zipkin.BinaryAnnotation in project zipkin by openzipkin.

the class MySQLSpanConsumer method accept.

/** Blocking version of {@link AsyncSpanConsumer#accept} */
@Override
public void accept(List<Span> spans) {
    if (spans.isEmpty())
        return;
    try (Connection conn = datasource.getConnection()) {
        DSLContext create = context.get(conn);
        List<Query> inserts = new ArrayList<>();
        for (Span span : spans) {
            Long overridingTimestamp = authoritativeTimestamp(span);
            Long timestamp = overridingTimestamp != null ? overridingTimestamp : guessTimestamp(span);
            Map<TableField<Record, ?>, Object> updateFields = new LinkedHashMap<>();
            if (!span.name.equals("") && !span.name.equals("unknown")) {
                updateFields.put(ZIPKIN_SPANS.NAME, span.name);
            }
            // replace any tentative timestamp with the authoritative one.
            if (overridingTimestamp != null) {
                updateFields.put(ZIPKIN_SPANS.START_TS, overridingTimestamp);
            }
            if (span.duration != null) {
                updateFields.put(ZIPKIN_SPANS.DURATION, span.duration);
            }
            InsertSetMoreStep<Record> insertSpan = create.insertInto(ZIPKIN_SPANS).set(ZIPKIN_SPANS.TRACE_ID, span.traceId).set(ZIPKIN_SPANS.ID, span.id).set(ZIPKIN_SPANS.PARENT_ID, span.parentId).set(ZIPKIN_SPANS.NAME, span.name).set(ZIPKIN_SPANS.DEBUG, span.debug).set(ZIPKIN_SPANS.START_TS, timestamp).set(ZIPKIN_SPANS.DURATION, span.duration);
            if (span.traceIdHigh != 0 && schema.hasTraceIdHigh) {
                insertSpan.set(ZIPKIN_SPANS.TRACE_ID_HIGH, span.traceIdHigh);
            }
            inserts.add(updateFields.isEmpty() ? insertSpan.onDuplicateKeyIgnore() : insertSpan.onDuplicateKeyUpdate().set(updateFields));
            for (Annotation annotation : span.annotations) {
                InsertSetMoreStep<Record> insert = create.insertInto(ZIPKIN_ANNOTATIONS).set(ZIPKIN_ANNOTATIONS.TRACE_ID, span.traceId).set(ZIPKIN_ANNOTATIONS.SPAN_ID, span.id).set(ZIPKIN_ANNOTATIONS.A_KEY, annotation.value).set(ZIPKIN_ANNOTATIONS.A_TYPE, -1).set(ZIPKIN_ANNOTATIONS.A_TIMESTAMP, annotation.timestamp);
                if (span.traceIdHigh != 0 && schema.hasTraceIdHigh) {
                    insert.set(ZIPKIN_ANNOTATIONS.TRACE_ID_HIGH, span.traceIdHigh);
                }
                if (annotation.endpoint != null) {
                    insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_SERVICE_NAME, annotation.endpoint.serviceName);
                    insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_IPV4, annotation.endpoint.ipv4);
                    if (annotation.endpoint.ipv6 != null && schema.hasIpv6) {
                        insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_IPV6, annotation.endpoint.ipv6);
                    }
                    insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_PORT, annotation.endpoint.port);
                }
                inserts.add(insert.onDuplicateKeyIgnore());
            }
            for (BinaryAnnotation annotation : span.binaryAnnotations) {
                InsertSetMoreStep<Record> insert = create.insertInto(ZIPKIN_ANNOTATIONS).set(ZIPKIN_ANNOTATIONS.TRACE_ID, span.traceId).set(ZIPKIN_ANNOTATIONS.SPAN_ID, span.id).set(ZIPKIN_ANNOTATIONS.A_KEY, annotation.key).set(ZIPKIN_ANNOTATIONS.A_VALUE, annotation.value).set(ZIPKIN_ANNOTATIONS.A_TYPE, annotation.type.value).set(ZIPKIN_ANNOTATIONS.A_TIMESTAMP, timestamp);
                if (span.traceIdHigh != 0 && schema.hasTraceIdHigh) {
                    insert.set(ZIPKIN_ANNOTATIONS.TRACE_ID_HIGH, span.traceIdHigh);
                }
                if (annotation.endpoint != null) {
                    insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_SERVICE_NAME, annotation.endpoint.serviceName);
                    insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_IPV4, annotation.endpoint.ipv4);
                    if (annotation.endpoint.ipv6 != null && schema.hasIpv6) {
                        insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_IPV6, annotation.endpoint.ipv6);
                    }
                    insert.set(ZIPKIN_ANNOTATIONS.ENDPOINT_PORT, annotation.endpoint.port);
                }
                inserts.add(insert.onDuplicateKeyIgnore());
            }
        }
        create.batch(inserts).execute();
    } catch (SQLException e) {
        // TODO
        throw new RuntimeException(e);
    }
}
Also used : Query(org.jooq.Query) SQLException(java.sql.SQLException) Connection(java.sql.Connection) ArrayList(java.util.ArrayList) DSLContext(org.jooq.DSLContext) TableField(org.jooq.TableField) Span(zipkin.Span) Annotation(zipkin.Annotation) BinaryAnnotation(zipkin.BinaryAnnotation) LinkedHashMap(java.util.LinkedHashMap) BinaryAnnotation(zipkin.BinaryAnnotation) Record(org.jooq.Record)

Example 9 with BinaryAnnotation

use of zipkin.BinaryAnnotation in project zipkin by openzipkin.

the class CorrectForClockSkew method adjustTimestamps.

/** If any annotation has an IP with skew associated, adjust accordingly. */
static Span adjustTimestamps(Span span, ClockSkew skew) {
    List<Annotation> annotations = null;
    Long annotationTimestamp = null;
    for (int i = 0, length = span.annotations.size(); i < length; i++) {
        Annotation a = span.annotations.get(i);
        if (a.endpoint == null)
            continue;
        if (ipsMatch(skew.endpoint, a.endpoint)) {
            if (annotations == null)
                annotations = new ArrayList<>(span.annotations);
            if (span.timestamp != null && a.timestamp == span.timestamp) {
                annotationTimestamp = a.timestamp;
            }
            annotations.set(i, a.toBuilder().timestamp(a.timestamp - skew.skew).build());
        }
    }
    if (annotations != null) {
        Span.Builder builder = span.toBuilder().annotations(annotations);
        if (annotationTimestamp != null) {
            builder.timestamp(annotationTimestamp - skew.skew);
        }
        return builder.build();
    }
    // Search for a local span on the skewed endpoint
    for (int i = 0, length = span.binaryAnnotations.size(); i < length; i++) {
        BinaryAnnotation b = span.binaryAnnotations.get(i);
        if (b.endpoint == null)
            continue;
        if (b.key.equals(Constants.LOCAL_COMPONENT) && ipsMatch(skew.endpoint, b.endpoint)) {
            return span.toBuilder().timestamp(span.timestamp - skew.skew).build();
        }
    }
    return span;
}
Also used : BinaryAnnotation(zipkin.BinaryAnnotation) ArrayList(java.util.ArrayList) Span(zipkin.Span) Annotation(zipkin.Annotation) BinaryAnnotation(zipkin.BinaryAnnotation) Endpoint(zipkin.Endpoint)

Example 10 with BinaryAnnotation

use of zipkin.BinaryAnnotation in project zipkin by openzipkin.

the class SpanStoreTest method getTraces_manyTraces.

/**
   * Formerly, a bug was present where cassandra didn't index more than bucket count traces per
   * millisecond. This stores a lot of spans to ensure indexes work under high-traffic scenarios.
   */
@Test
public void getTraces_manyTraces() {
    int traceCount = 1000;
    Span span = TestObjects.LOTS_OF_SPANS[0];
    BinaryAnnotation b = span.binaryAnnotations.get(0);
    accept(Arrays.copyOfRange(TestObjects.LOTS_OF_SPANS, 0, traceCount));
    assertThat(store().getTraces(new QueryRequest.Builder().limit(traceCount).build())).hasSize(traceCount);
    QueryRequest.Builder builder = QueryRequest.builder().limit(traceCount).serviceName(b.endpoint.serviceName);
    assertThat(store().getTraces(builder.build())).hasSize(traceCount);
    assertThat(store().getTraces(builder.spanName(span.name).build())).hasSize(traceCount);
    assertThat(store().getTraces(builder.addBinaryAnnotation(b.key, new String(b.value)).build())).hasSize(traceCount);
}
Also used : BinaryAnnotation(zipkin.BinaryAnnotation) Span(zipkin.Span) Endpoint(zipkin.Endpoint) Test(org.junit.Test)

Aggregations

BinaryAnnotation (zipkin.BinaryAnnotation)13 Annotation (zipkin.Annotation)7 Test (org.junit.Test)6 Endpoint (zipkin.Endpoint)6 Span (zipkin.Span)5 ArrayList (java.util.ArrayList)4 LinkedHashSet (java.util.LinkedHashSet)3 LinkedHashMap (java.util.LinkedHashMap)2 QueryRequest (zipkin.storage.QueryRequest)2 SpanStoreTest (zipkin.storage.SpanStoreTest)2 BoundStatement (com.datastax.driver.core.BoundStatement)1 Connection (java.sql.Connection)1 SQLException (java.sql.SQLException)1 UUID (java.util.UUID)1 DSLContext (org.jooq.DSLContext)1 Query (org.jooq.Query)1 Record (org.jooq.Record)1 TableField (org.jooq.TableField)1 AnnotationUDT (zipkin.storage.cassandra3.Schema.AnnotationUDT)1 BinaryAnnotationUDT (zipkin.storage.cassandra3.Schema.BinaryAnnotationUDT)1