zipkin.server.brave.BraveConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for zipkin.server.brave.BraveConfiguration.java

Source

/**
 * Copyright 2015-2017 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.server.brave;

import brave.Tracer;
import brave.sampler.BoundarySampler;
import brave.sampler.Sampler;
import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.InheritableServerClientAndLocalSpanState;
import com.github.kristofa.brave.ServerClientAndLocalSpanState;
import com.github.kristofa.brave.TracerAdapter;
import java.io.IOException;
import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import zipkin.Codec;
import zipkin.Endpoint;
import zipkin.Span;
import zipkin.collector.CollectorMetrics;
import zipkin.internal.Nullable;
import zipkin.reporter.AsyncReporter;
import zipkin.reporter.Callback;
import zipkin.reporter.Encoding;
import zipkin.reporter.Reporter;
import zipkin.reporter.ReporterMetrics;
import zipkin.reporter.Sender;
import zipkin.server.ConditionalOnSelfTracing;
import zipkin.storage.StorageComponent;

import static zipkin.internal.Util.propagateIfFatal;

@Configuration
@ConditionalOnSelfTracing
@Import(ApiTracerConfiguration.class)
public class BraveConfiguration {

    /** This gets the lanIP without trying to lookup its name. */
    // http://stackoverflow.com/questions/8765578/get-local-ip-address-without-connecting-to-the-internet
    @Bean
    @Scope
    Endpoint local(@Value("${server.port:9411}") int port) {
        Endpoint.Builder builder = Endpoint.builder().serviceName("zipkin-server").port(port == -1 ? 0 : port);
        try {
            byte[] address = Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
                    .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
                    .filter(ip -> ip.isSiteLocalAddress()).findAny().get().getAddress();
            if (address.length == 4) {
                builder.ipv4(ByteBuffer.wrap(address).getInt());
            } else if (address.length == 16) {
                builder.ipv6(address);
            }
        } catch (Exception ignored) {
            builder.ipv4(127 << 24 | 1);
        }
        return builder.build();
    }

    // Note: there's a chicken or egg problem here. TracedStorageComponent wraps StorageComponent with
    // Brave. During initialization, if we eagerly reference StorageComponent from within Brave,
    // BraveTracedStorageComponentEnhancer won't be able to process it. TL;DR; if you take out Lazy
    // here, self-tracing will not affect the storage component, which reduces its effectiveness.
    @Bean
    Reporter<Span> reporter(@Lazy StorageComponent storage,
            @Value("${zipkin.self-tracing.flush-interval:1}") int flushInterval, CollectorMetrics metrics) {
        return AsyncReporter.builder(new LocalSender(storage)).messageTimeout(flushInterval, TimeUnit.SECONDS)
                .metrics(new ReporterMetricsAdapter(metrics.forTransport("local"))).build();
    }

    @Bean
    ServerClientAndLocalSpanState braveState(@Qualifier("local") Endpoint local) {
        com.twitter.zipkin.gen.Endpoint braveEndpoint = com.twitter.zipkin.gen.Endpoint.builder().ipv4(local.ipv4)
                .ipv6(local.ipv6).port(local.port).serviceName(local.serviceName).build();
        return new InheritableServerClientAndLocalSpanState(braveEndpoint);
    }

    @Bean
    Tracer braveTracer(Reporter<Span> reporter, @Qualifier("local") Endpoint local,
            @Value("${zipkin.self-tracing.sample-rate:1.0}") float rate) {
        return Tracer.newBuilder().localEndpoint(local)
                .sampler(rate < 0.01 ? BoundarySampler.create(rate) : Sampler.create(rate)).reporter(reporter)
                .build();
    }

    @Bean
    Brave brave(Tracer braveTracer, ServerClientAndLocalSpanState braveState) {
        return TracerAdapter.newBrave(braveTracer, braveState);
    }

    /**
     * Defined locally as StorageComponent is a lazy proxy, and we need to avoid eagerly calling it.
     */
    static final class LocalSender implements Sender {
        private final StorageComponent delegate;

        LocalSender(StorageComponent delegate) {
            this.delegate = delegate;
        }

        @Override
        public Encoding encoding() {
            return Encoding.THRIFT;
        }

        @Override
        public int messageMaxBytes() {
            return 5 * 1024 * 1024; // arbitrary
        }

        @Override
        public int messageSizeInBytes(List<byte[]> list) {
            return Encoding.THRIFT.listSizeInBytes(list);
        }

        @Override
        public void sendSpans(List<byte[]> encodedSpans, Callback callback) {
            try {
                List<Span> spans = new ArrayList<>(encodedSpans.size());
                for (byte[] encodedSpan : encodedSpans) {
                    spans.add(Codec.THRIFT.readSpan(encodedSpan));
                }
                delegate.asyncSpanConsumer().accept(spans, new CallbackAdapter(callback));
            } catch (Throwable t) {
                propagateIfFatal(t);
                callback.onError(t);
            }
        }

        @Override
        public CheckResult check() {
            return CheckResult.OK;
        }

        @Override
        public void close() throws IOException {
        }
    }

    static final class CallbackAdapter implements zipkin.storage.Callback<Void> {
        final Callback delegate;

        CallbackAdapter(Callback delegate) {
            this.delegate = delegate;
        }

        @Override
        public void onSuccess(@Nullable Void aVoid) {
            delegate.onComplete();
        }

        @Override
        public void onError(Throwable throwable) {
            delegate.onError(throwable);
        }
    }

    static final class ReporterMetricsAdapter implements ReporterMetrics {
        final CollectorMetrics delegate;

        ReporterMetricsAdapter(CollectorMetrics delegate) {
            this.delegate = delegate;
        }

        @Override
        public void incrementMessages() {
            delegate.incrementMessages();
        }

        @Override
        public void incrementMessagesDropped(Throwable throwable) {
            delegate.incrementMessagesDropped();
        }

        @Override
        public void incrementSpans(int i) {
            delegate.incrementSpans(i);
        }

        @Override
        public void incrementSpanBytes(int i) {
            delegate.incrementBytes(i);
        }

        @Override
        public void incrementMessageBytes(int i) {
        }

        @Override
        public void incrementSpansDropped(int i) {
            delegate.incrementMessagesDropped();
        }

        @Override
        public void updateQueuedSpans(int i) {
        }

        @Override
        public void updateQueuedBytes(int i) {
        }
    }
}