zipkin2.storage.cassandra.SelectTraceIdsFromSpan Maven / Gradle / Ivy
/*
* Copyright The OpenZipkin Authors
* SPDX-License-Identifier: Apache-2.0
*/
package zipkin2.storage.cassandra;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
import com.datastax.oss.driver.api.core.cql.BoundStatementBuilder;
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
import com.datastax.oss.driver.api.core.cql.Row;
import com.google.auto.value.AutoValue;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletionStage;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import zipkin2.Call;
import zipkin2.internal.Nullable;
import zipkin2.storage.cassandra.CassandraSpanStore.TimestampRange;
import zipkin2.storage.cassandra.internal.call.AccumulateAllResults;
import zipkin2.storage.cassandra.internal.call.ResultSetFutureCall;
import static zipkin2.storage.cassandra.Schema.TABLE_SPAN;
/**
* Selects from the {@link Schema#TABLE_SPAN} using data in the partition key or SASI indexes.
*
* Note: While queries here use "ALLOW FILTERING", they do so within a SASI clause, and only
* return (traceId, timestamp) tuples. This means the entire spans table is not scanned, unless the
* time range implies that.
*
*
The spans table is sorted descending by timestamp. When a query includes only a time range,
* the first N rows are already in the correct order. However, the cardinality of rows is a function
* of span count, not trace count. This implies an over-fetch function based on average span count
* per trace in order to achieve N distinct trace IDs. For example if there are 3 spans per trace,
* and over-fetch function of 3 * intended limit will work. See {@link
* CassandraStorage#indexFetchMultiplier} for an associated parameter.
*/
final class SelectTraceIdsFromSpan extends ResultSetFutureCall {
@AutoValue abstract static class Input {
@Nullable abstract String l_service();
@Nullable abstract String annotation_query();
abstract UUID start_ts();
abstract UUID end_ts();
abstract int limit_();
}
static final class Factory {
final CqlSession session;
final PreparedStatement withAnnotationQuery, withServiceAndAnnotationQuery;
Factory(CqlSession session) {
this.session = session;
String querySuffix = """
annotation_query LIKE ?\
AND ts_uuid>=?\
AND ts_uuid<=?\
LIMIT ?\
ALLOW FILTERING\
""";
this.withAnnotationQuery = session.prepare("SELECT trace_id,ts"
+ " FROM " + TABLE_SPAN
+ " WHERE " + querySuffix);
this.withServiceAndAnnotationQuery = session.prepare("SELECT trace_id,ts"
+ " FROM " + TABLE_SPAN
+ " WHERE l_service=:l_service"
+ " AND " + querySuffix);
}
Call