use of zipkin.Annotation 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);
}
}
use of zipkin.Annotation 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;
}
use of zipkin.Annotation in project zipkin by openzipkin.
the class CorrectForClockSkew method getClockSkew.
/** Use client/server annotations to determine if there's clock skew. */
@Nullable
static ClockSkew getClockSkew(Span span) {
Map<String, Annotation> annotations = asMap(span.annotations);
Annotation clientSend = annotations.get(Constants.CLIENT_SEND);
Annotation clientRecv = annotations.get(Constants.CLIENT_RECV);
Annotation serverRecv = annotations.get(Constants.SERVER_RECV);
Annotation serverSend = annotations.get(Constants.SERVER_SEND);
if (clientSend == null || clientRecv == null || serverRecv == null || serverSend == null) {
return null;
}
Endpoint server = serverRecv.endpoint != null ? serverRecv.endpoint : serverSend.endpoint;
if (server == null)
return null;
Endpoint client = clientSend.endpoint != null ? clientSend.endpoint : clientRecv.endpoint;
if (client == null)
return null;
// There's no skew if the RPC is going to itself
if (ipsMatch(server, client))
return null;
long clientDuration = clientRecv.timestamp - clientSend.timestamp;
long serverDuration = serverSend.timestamp - serverRecv.timestamp;
// This breaks if client duration is smaller than server (due to async return for example).
if (clientDuration < serverDuration)
return null;
long latency = (clientDuration - serverDuration) / 2;
// We can't see skew when send happens before receive
if (latency < 0)
return null;
long skew = serverRecv.timestamp - latency - clientSend.timestamp;
if (skew != 0L) {
return new ClockSkew(server, skew);
}
return null;
}
use of zipkin.Annotation in project zipkin by openzipkin.
the class SpanStoreTest method whenSpanTimestampIsMissingClientSendIsPreferred.
/**
* Spans report depth-first. Make sure the client timestamp is preferred when instrumentation
* don't add a timestamp.
*/
@Test
public void whenSpanTimestampIsMissingClientSendIsPreferred() {
Endpoint frontend = Endpoint.create("frontend", 192 << 24 | 168 << 16 | 2);
Annotation cs = Annotation.create((today + 50) * 1000, CLIENT_SEND, frontend);
Annotation cr = Annotation.create((today + 150) * 1000, CLIENT_RECV, frontend);
Endpoint backend = Endpoint.create("backend", 192 << 24 | 168 << 16 | 2);
Annotation sr = Annotation.create((today + 95) * 1000, SERVER_RECV, backend);
Annotation ss = Annotation.create((today + 100) * 1000, SERVER_SEND, backend);
Span span = Span.builder().traceId(1).name("method1").id(666).build();
// Simulate the server-side of a shared span arriving first
accept(span.toBuilder().addAnnotation(sr).addAnnotation(ss).build());
accept(span.toBuilder().addAnnotation(cs).addAnnotation(cr).build());
// Make sure that the client's timestamp won
assertThat(store().getTrace(span1.traceIdHigh, span.traceId)).containsExactly(span.toBuilder().timestamp(cs.timestamp).duration(cr.timestamp - cs.timestamp).annotations(asList(cs, sr, ss, cr)).build());
}
use of zipkin.Annotation in project zipkin by openzipkin.
the class QueryRequest method test.
/** Tests the supplied trace against the current request */
public boolean test(List<Span> spans) {
Long timestamp = ApplyTimestampAndDuration.guessTimestamp(spans.get(0));
if (timestamp == null || timestamp < (endTs - lookback) * 1000 || timestamp > endTs * 1000) {
return false;
}
Set<String> serviceNames = new LinkedHashSet<>();
boolean testedDuration = minDuration == null && maxDuration == null;
String spanNameToMatch = spanName;
Set<String> annotationsToMatch = new LinkedHashSet<>(annotations);
Map<String, String> binaryAnnotationsToMatch = new LinkedHashMap<>(binaryAnnotations);
Set<String> currentServiceNames = new LinkedHashSet<>();
for (Span span : spans) {
currentServiceNames.clear();
for (Annotation a : span.annotations) {
if (appliesToServiceName(a.endpoint, serviceName)) {
annotationsToMatch.remove(a.value);
}
if (a.endpoint != null) {
serviceNames.add(a.endpoint.serviceName);
currentServiceNames.add(a.endpoint.serviceName);
}
}
for (BinaryAnnotation b : span.binaryAnnotations) {
if (appliesToServiceName(b.endpoint, serviceName) && b.type == BinaryAnnotation.Type.STRING && new String(b.value, UTF_8).equals(binaryAnnotationsToMatch.get(b.key))) {
binaryAnnotationsToMatch.remove(b.key);
}
if (b.endpoint != null) {
serviceNames.add(b.endpoint.serviceName);
currentServiceNames.add(b.endpoint.serviceName);
}
}
if ((serviceName == null || currentServiceNames.contains(serviceName)) && !testedDuration) {
if (minDuration != null && maxDuration != null) {
testedDuration = span.duration >= minDuration && span.duration <= maxDuration;
} else if (minDuration != null) {
testedDuration = span.duration >= minDuration;
}
}
if (span.name.equals(spanNameToMatch)) {
spanNameToMatch = null;
}
}
return (serviceName == null || serviceNames.contains(serviceName)) && spanNameToMatch == null && annotationsToMatch.isEmpty() && binaryAnnotationsToMatch.isEmpty() && testedDuration;
}
Aggregations