CassandraSpanStore implements SpanStore, Traces, ServiceAndSpanNames { @Override public Call<List<List<Span>>> getTraces(QueryRequest request) { if (!searchEnabled) return Call.emptyList(); TimestampRange timestampRange = timestampRange(request); 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) ); } 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)); } IntersectKeySets intersectedTraceIds = new IntersectKeySets(callsToIntersect); return intersectedTraceIds.flatMap(spans.newFlatMapper(request)); } CassandraSpanStore(CassandraStorage storage); @Override Call<List<List<Span>>> getTraces(QueryRequest request); @Override Call<List<Span>> getTrace(String traceId); @Override Call<List<List<Span>>> getTraces(Iterable<String> traceIds); @Override Call<List<String>> getServiceNames(); @Override Call<List<String>> getRemoteServiceNames(String serviceName); @Override Call<List<String>> getSpanNames(String serviceName); @Override Call<List<DependencyLink>> getDependencies(long endTs, long lookback);  }
@Test public void getTraces_fansOutAgainstServices() { Call<List<List<Span>>> call = spanStore.getTraces(queryBuilder.build()); assertThat(call.toString()).contains(FlatMapServicesToInputs.class.getSimpleName()); }
@Test public void getTraces_withSpanNameButNoServiceName() { Call<List<List<Span>>> call = spanStore.getTraces(queryBuilder.spanName("get").build()); assertThat(call.toString()) .contains(FlatMapServicesToInputs.class.getSimpleName()) .contains("span=get"); }
@Test public void getTraces_withTagButNoServiceName() { Call<List<List<Span>>> call = spanStore.getTraces( queryBuilder.annotationQuery(Collections.singletonMap("environment", "production")).build()); assertThat(call.toString()) .doesNotContain(FlatMapServicesToInputs.class.getSimpleName()) .contains("l_service=null, annotation_query=environment=production"); }
@Test public void getTraces_withDurationButNoServiceName() { Call<List<List<Span>>> call = spanStore.getTraces(queryBuilder.minDuration(1000L).build()); assertThat(call.toString()) .contains(FlatMapServicesToInputs.class.getSimpleName()) .contains("start_duration=1,"); }
@Test public void getTraces_withRemoteServiceNameButNoServiceName() { Call<List<List<Span>>> call = spanStore.getTraces(queryBuilder.remoteServiceName("backend").build()); assertThat(call.toString()) .contains(FlatMapServicesToInputs.class.getSimpleName()) .contains("remote_service=backend,") .doesNotContain("span="); }
@Test public void getTraces() { Call<List<List<Span>>> call = spanStore.getTraces(queryBuilder.serviceName("frontend").build()); assertThat(call.toString()).contains("service=frontend, span=,"); }
@Test public void getTraces_withSpanName() { Call<List<List<Span>>> call = spanStore.getTraces( queryBuilder.serviceName("frontend").spanName("get").build()); assertThat(call.toString()) .contains("service=frontend, span=get,"); }
@Test public void getTraces_withRemoteServiceName() { Call<List<List<Span>>> call = spanStore.getTraces( queryBuilder.serviceName("frontend").remoteServiceName("backend").build()); assertThat(call.toString()) .contains("service=frontend, remote_service=backend,") .doesNotContain("service=frontend, span="); }
@Test public void getTraces_withSpanNameAndRemoteServiceName() { Call<List<List<Span>>> call = spanStore.getTraces( queryBuilder.serviceName("frontend").remoteServiceName("backend").spanName("get").build()); assertThat(call.toString()) .contains("service=frontend, remote_service=backend,") .contains("service=frontend, span=get,"); }