use of zipkin.Span 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 + "\"]"));
}
use of zipkin.Span in project zipkin by openzipkin.
the class ZipkinServerIntegrationTest method readsRawTrace.
@Test
public void readsRawTrace() throws Exception {
Span span = TRACE.get(0);
// write the span to the server, twice
performAsync(post("/api/v1/spans").content(Codec.JSON.writeSpans(asList(span)))).andExpect(status().isAccepted());
performAsync(post("/api/v1/spans").content(Codec.JSON.writeSpans(asList(span)))).andExpect(status().isAccepted());
// sleep as the the storage operation is async
Thread.sleep(1500);
// Default will merge by span id
mockMvc.perform(get(format("/api/v1/trace/%016x", span.traceId))).andExpect(status().isOk()).andExpect(content().string(new String(Codec.JSON.writeSpans(asList(span)), UTF_8)));
// In the in-memory (or cassandra) stores, a raw read will show duplicate span rows.
mockMvc.perform(get(format("/api/v1/trace/%016x?raw", span.traceId))).andExpect(status().isOk()).andExpect(content().string(new String(Codec.JSON.writeSpans(asList(span, span)), UTF_8)));
}
use of zipkin.Span in project zipkin by openzipkin.
the class CassandraSpanConsumer method accept.
/**
* This fans out into many requests, last count was 8 * spans.size. If any of these fail, the
* returned future will fail. Most callers drop or log the result.
*/
@Override
public ListenableFuture<Void> accept(List<Span> rawSpans) {
ImmutableSet.Builder<ListenableFuture<?>> futures = ImmutableSet.builder();
ImmutableList.Builder<Span> spans = ImmutableList.builder();
for (Span span : rawSpans) {
// indexing occurs by timestamp, so derive one if not present.
Long timestamp = guessTimestamp(span);
spans.add(span);
boolean isServerRecvSpan = isServerRecvSpan(span);
futures.add(storeSpan(span.traceId, timestamp != null ? timestamp : 0L, isServerRecvSpan, String.format("%s%d_%d_%d", span.traceIdHigh == 0 ? "" : span.traceIdHigh + "_", span.id, span.annotations.hashCode(), span.binaryAnnotations.hashCode()), // store the raw span without any adjustments
ByteBuffer.wrap(Codec.THRIFT.writeSpan(span))));
for (String serviceName : span.serviceNames()) {
// SpanStore.getServiceNames
futures.add(storeServiceName(serviceName));
if (!span.name.isEmpty()) {
// SpanStore.getSpanNames
futures.add(storeSpanName(serviceName, span.name));
}
}
}
futures.addAll(indexer.index(spans.build()));
return transform(Futures.allAsList(futures.build()), TO_VOID);
}
use of zipkin.Span in project zipkin by openzipkin.
the class CassandraSpanConsumer method accept.
/**
* This fans out into many requests, last count was 2 * spans.size. If any of these fail, the
* returned future will fail. Most callers drop or log the result.
*/
@Override
public ListenableFuture<Void> accept(List<Span> rawSpans) {
ImmutableSet.Builder<ListenableFuture<?>> futures = ImmutableSet.builder();
for (Span span : rawSpans) {
// indexing occurs by timestamp, so derive one if not present.
Long timestamp = guessTimestamp(span);
TraceIdUDT traceId = new TraceIdUDT(span.traceIdHigh, span.traceId);
boolean isServerRecvSpan = isServerRecvSpan(span);
futures.add(storeSpan(span, traceId, isServerRecvSpan, timestamp));
for (String serviceName : span.serviceNames()) {
// QueryRequest.min/maxDuration
if (timestamp != null) {
// Contract for Repository.storeTraceServiceSpanName is to store the span twice, once with
// the span name and another with empty string.
futures.add(storeTraceServiceSpanName(serviceName, span.name, timestamp, span.duration, traceId));
if (!span.name.isEmpty()) {
// If span.name == "", this would be redundant
futures.add(storeTraceServiceSpanName(serviceName, "", timestamp, span.duration, traceId));
}
futures.add(storeServiceSpanName(serviceName, span.name));
}
}
}
return transform(Futures.allAsList(futures.build()), TO_VOID);
}
use of zipkin.Span in project zipkin by openzipkin.
the class Indexer method index.
ImmutableSet<ListenableFuture<?>> index(List<Span> spans) {
// First parse each span into partition keys used to support query requests
Builder<PartitionKeyToTraceId, Long> parsed = ImmutableSetMultimap.builder();
for (Span span : spans) {
Long timestamp = guessTimestamp(span);
if (timestamp == null)
continue;
for (String partitionKey : index.partitionKeys(span)) {
parsed.put(new PartitionKeyToTraceId(index.table(), partitionKey, span.traceId), // index precision is millis
1000 * (timestamp / 1000));
}
}
// The parsed results may include inserts that already occur, or are redundant as they don't
// impact QueryRequest.endTs or QueryRequest.loopback. For example, a parsed timestamp could
// be between timestamps of rows that already exist for a particular trace.
ImmutableSetMultimap<PartitionKeyToTraceId, Long> maybeInsert = parsed.build();
ImmutableSetMultimap<PartitionKeyToTraceId, Long> toInsert;
if (sharedState == null) {
// special-case when caching is disabled.
toInsert = maybeInsert;
} else {
// Optimized results will be smaller when the input includes traces with local spans, or when
// other threads indexed the same trace.
toInsert = entriesThatIncreaseGap(sharedState, maybeInsert);
if (maybeInsert.size() > toInsert.size() && LOG.isDebugEnabled()) {
int delta = maybeInsert.size() - toInsert.size();
LOG.debug("optimized out {}/{} inserts into {}", delta, maybeInsert.size(), index.table());
}
}
// For each entry, insert a new row in the index table asynchronously
ImmutableSet.Builder<ListenableFuture<?>> result = ImmutableSet.builder();
for (Map.Entry<PartitionKeyToTraceId, Long> entry : toInsert.entries()) {
BoundStatement bound = bindWithName(prepared, boundName).setLong("trace_id", entry.getKey().traceId).setBytesUnsafe("ts", timestampCodec.serialize(entry.getValue()));
if (indexTtl != null) {
bound.setInt("ttl_", indexTtl);
}
index.bindPartitionKey(bound, entry.getKey().partitionKey);
result.add(session.executeAsync(bound));
}
return result.build();
}
Aggregations