Search in sources :

Example 1 with QueryRequest

use of zipkin2.storage.QueryRequest in project zipkin by openzipkin.

the class CassandraUtilTest method annotationKeys_emptyRequest.

@Test
public void annotationKeys_emptyRequest() {
    QueryRequest request = QueryRequest.newBuilder().endTs(System.currentTimeMillis()).limit(10).serviceName("test").lookback(86400000L).build();
    assertThat(CassandraUtil.annotationKeys(request)).isEmpty();
}
Also used : QueryRequest(zipkin2.storage.QueryRequest) Test(org.junit.Test)

Example 2 with QueryRequest

use of zipkin2.storage.QueryRequest in project zipkin by openzipkin.

the class CassandraUtilTest method annotationKeys.

@Test
public void annotationKeys() {
    QueryRequest request = QueryRequest.newBuilder().endTs(System.currentTimeMillis()).limit(10).lookback(86400000L).serviceName("service").parseAnnotationQuery("error and http.method=GET").build();
    assertThat(CassandraUtil.annotationKeys(request)).containsExactly("error", "http.method=GET");
}
Also used : QueryRequest(zipkin2.storage.QueryRequest) Test(org.junit.Test)

Example 3 with QueryRequest

use of zipkin2.storage.QueryRequest in project zipkin by openzipkin.

the class ITEnsureSchema method worksWithOldSchema.

/**
 * This tests we don't accidentally rely on new indexes such as autocomplete tags
 */
@Test
void worksWithOldSchema(TestInfo testInfo) throws Exception {
    String testSuffix = testSuffix(testInfo);
    Schema.applyCqlFile(storage.keyspace, session(), "/zipkin2-schema.cql");
    Schema.applyCqlFile(storage.keyspace, session(), "/zipkin2-schema-indexes-original.cql");
    // Ensure the storage component is functional before proceeding
    CheckResult check = storage.check();
    if (!check.ok()) {
        throw new AssertionError("Could not connect to storage: " + check.error().getMessage(), check.error());
    }
    List<Span> trace = newTrace(testSuffix);
    accept(trace);
    assertGetTraceReturns(trace.get(0).traceId(), trace);
    assertThat(storage.autocompleteTags().getValues("environment").execute()).isEmpty();
    String serviceName = trace.get(0).localServiceName();
    assertThat(storage.serviceAndSpanNames().getRemoteServiceNames(serviceName).execute()).isEmpty();
    QueryRequest request = requestBuilder().serviceName(serviceName).remoteServiceName(appendSuffix(BACKEND.serviceName(), testSuffix)).build();
    // Make sure there's an error if a query will return incorrectly vs returning invalid results
    assertThatThrownBy(() -> storage.spanStore().getTraces(request)).isInstanceOf(IllegalArgumentException.class).hasMessage("remoteService=" + trace.get(1).remoteServiceName() + " unsupported due to missing table remote_service_by_service");
}
Also used : QueryRequest(zipkin2.storage.QueryRequest) CheckResult(zipkin2.CheckResult) Span(zipkin2.Span) Test(org.junit.jupiter.api.Test)

Example 4 with QueryRequest

use of zipkin2.storage.QueryRequest 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));
}
Also used : Call(zipkin2.Call) ArrayList(java.util.ArrayList) IntersectKeySets(zipkin2.storage.cassandra.internal.call.IntersectKeySets)

Example 5 with QueryRequest

use of zipkin2.storage.QueryRequest in project zipkin by openzipkin.

the class CassandraUtil method annotationQuery.

/**
 * Returns a set of annotation getValues and tags joined on equals, delimited by ░
 *
 * <p>Values over {@link RecyclableBuffers#SHORT_STRING_LENGTH} are not considered. Zipkin's
 * {@link QueryRequest#annotationQuery()} are equals match. Not all values are lookup values. For
 * example, {@code sql.query} isn't something that is likely to be looked up by value and indexing
 * that could add a potentially kilobyte partition key on {@link Schema#TABLE_SPAN}
 *
 * @see QueryRequest#annotationQuery()
 */
@Nullable
static String annotationQuery(Span span) {
    if (span.annotations().isEmpty() && span.tags().isEmpty())
        return null;
    // as very unlikely to be in the query
    char delimiter = '░';
    StringBuilder result = new StringBuilder().append(delimiter);
    for (Annotation a : span.annotations()) {
        if (a.value().length() > SHORT_STRING_LENGTH)
            continue;
        result.append(a.value()).append(delimiter);
    }
    for (Map.Entry<String, String> tag : span.tags().entrySet()) {
        if (tag.getValue().length() > SHORT_STRING_LENGTH)
            continue;
        // search is possible by key alone
        result.append(tag.getKey()).append(delimiter);
        result.append(tag.getKey()).append('=').append(tag.getValue()).append(delimiter);
    }
    return result.length() == 1 ? null : result.toString();
}
Also used : TreeMap(java.util.TreeMap) Map(java.util.Map) Annotation(zipkin2.Annotation) Nullable(zipkin2.internal.Nullable)

Aggregations

QueryRequest (zipkin2.storage.QueryRequest)7 Map (java.util.Map)3 Test (org.junit.Test)3 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Test (org.junit.jupiter.api.Test)2 Span (zipkin2.Span)2 Blocking (com.linecorp.armeria.server.annotation.Blocking)1 Get (com.linecorp.armeria.server.annotation.Get)1 Arrays.asList (java.util.Arrays.asList)1 LinkedHashMap (java.util.LinkedHashMap)1 TreeMap (java.util.TreeMap)1 Record (org.jooq.Record)1 SelectField (org.jooq.SelectField)1 Annotation (zipkin2.Annotation)1 Call (zipkin2.Call)1 CheckResult (zipkin2.CheckResult)1 Endpoint (zipkin2.Endpoint)1 Aggregation (zipkin2.elasticsearch.internal.client.Aggregation)1 SearchRequest (zipkin2.elasticsearch.internal.client.SearchRequest)1