zipkin.cassandra.CassandraSpanConsumer.java Source code

Java tutorial

Introduction

Here is the source code for zipkin.cassandra.CassandraSpanConsumer.java

Source

/**
 * Copyright 2015-2016 The OpenZipkin Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package zipkin.cassandra;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import org.twitter.zipkin.storage.cassandra.Repository;
import zipkin.Codec;
import zipkin.Span;
import zipkin.internal.ApplyTimestampAndDuration;
import zipkin.spanstore.guava.GuavaSpanConsumer;

import static com.google.common.util.concurrent.Futures.transform;
import static zipkin.cassandra.CassandraUtil.annotationKeys;

// Extracted for readability
final class CassandraSpanConsumer implements GuavaSpanConsumer {
    private static final Function<Object, Void> TO_VOID = Functions.<Void>constant(null);

    private final Repository repository;
    private final int spanTtl;
    private final int indexTtl;

    CassandraSpanConsumer(Repository repository, int spanTtl, int indexTtl) {
        this.repository = repository;
        this.spanTtl = spanTtl;
        this.indexTtl = indexTtl;
    }

    @Override
    public ListenableFuture<Void> accept(List<Span> spans) {
        List<ListenableFuture<?>> futures = new LinkedList<>();
        for (Span span : spans) {
            span = ApplyTimestampAndDuration.apply(span);
            futures.add(repository.storeSpan(span.traceId, span.timestamp != null ? span.timestamp : 0L,
                    String.format("%d_%d_%d", span.id, span.annotations.hashCode(),
                            span.binaryAnnotations.hashCode()),
                    ByteBuffer.wrap(Codec.THRIFT.writeSpan(span)), spanTtl));

            for (String serviceName : span.serviceNames()) {
                // SpanStore.getServiceNames
                futures.add(repository.storeServiceName(serviceName, indexTtl));
                if (!span.name.isEmpty()) {
                    // SpanStore.getSpanNames
                    futures.add(repository.storeSpanName(serviceName, span.name, indexTtl));
                }

                if (span.timestamp != null) {
                    // QueryRequest.serviceName
                    futures.add(repository.storeTraceIdByServiceName(serviceName, span.timestamp, span.traceId,
                            indexTtl));

                    // QueryRequest.spanName
                    if (!span.name.isEmpty()) {
                        futures.add(repository.storeTraceIdBySpanName(serviceName, span.name, span.timestamp,
                                span.traceId, indexTtl));
                    }

                    // QueryRequest.min/maxDuration
                    if (span.duration != null) {
                        // Contract for Repository.storeTraceIdByDuration is to store the span twice, once with
                        // the span name and another with empty string.
                        futures.add(repository.storeTraceIdByDuration(serviceName, span.name, span.timestamp,
                                span.duration, span.traceId, indexTtl));
                        if (!span.name.isEmpty()) { // If span.name == "", this would be redundant
                            repository.storeTraceIdByDuration(serviceName, "", span.timestamp, span.duration,
                                    span.traceId, indexTtl);
                        }
                    }
                }
            }
            // QueryRequest.annotations/binaryAnnotations
            if (span.timestamp != null) {
                for (ByteBuffer annotation : annotationKeys(span)) {
                    futures.add(repository.storeTraceIdByAnnotation(annotation, span.timestamp, span.traceId,
                            indexTtl));
                }
            }
        }
        return transform(Futures.allAsList(futures), TO_VOID);
    }
}