use of zipkin2.storage.cassandra.internal.call.IntersectKeySets in project zipkin by openzipkin.
the class CassandraSpanStore method getTraces.
/**
* This fans out into a number of requests corresponding to query input. In simplest case, there
* is less than a day of data queried, and only one expression. This implies one call to fetch
* trace IDs and another to retrieve the span details.
*
* <p>The amount of backend calls increase in dimensions of query complexity, days of data, and
* limit of traces requested. For example, a query like "http.path=/foo and error" will be two
* select statements for the expression, possibly follow-up calls for pagination (when over 5K
* rows match). Once IDs are parsed, there's one call for each 5K rows of span data. This means
* "http.path=/foo and error" is minimally 3 network calls, the first two in parallel.
*/
@Override
public Call<List<List<Span>>> getTraces(QueryRequest request) {
if (!searchEnabled)
return Call.emptyList();
TimestampRange timestampRange = timestampRange(request);
// If we have to make multiple queries, over fetch on indexes as they don't return distinct
// (trace id, timestamp) rows. This mitigates intersection resulting in < limit traces
final int traceIndexFetchSize = request.limit() * indexFetchMultiplier;
List<Call<Map<String, Long>>> callsToIntersect = new ArrayList<>();
List<String> annotationKeys = CassandraUtil.annotationKeys(request);
for (String annotationKey : annotationKeys) {
if (spanTable == null) {
throw new IllegalArgumentException(request.annotationQueryString() + " query unsupported due to missing annotation_query index");
}
callsToIntersect.add(spanTable.newCall(request.serviceName(), annotationKey, timestampRange, traceIndexFetchSize));
}
// Bucketed calls can be expensive when service name isn't specified. This guards against abuse.
if (request.remoteServiceName() != null || request.spanName() != null || request.minDuration() != null || callsToIntersect.isEmpty()) {
callsToIntersect.add(newBucketedTraceIdCall(request, timestampRange, traceIndexFetchSize));
}
if (callsToIntersect.size() == 1) {
return callsToIntersect.get(0).map(traceIdsSortedByDescTimestamp()).flatMap(spans.newFlatMapper(request));
}
// We achieve the AND goal, by intersecting each of the key sets.
IntersectKeySets intersectedTraceIds = new IntersectKeySets(callsToIntersect);
// @xxx the sorting by timestamp desc is broken here^
return intersectedTraceIds.flatMap(spans.newFlatMapper(request));
}
Aggregations