Skip to content

Latest commit

 

History

History
 
 

zipkin-brave-java-spring-boot-web

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Zipkin, Spring-boot and SignalFx

About

This example project demonstrates how to use Spring Boot, Zipkin, and SignalFx together. This example uses the Java Spring Zipkin Project and demonstrates how to configure the Java Spring Zipkin project to report traces to SignalFx.

References

Configuration

The example project demonstrates the following modifications to a Spring Application to send your trace spans to SignalFx. The following changes assume you're already using the Spring Boot Web libraries.

Required Configuration

1. Add the required dependencies

Maven

<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
<dependency>
    <groupId>io.opentracing.contrib</groupId>
    <artifactId>opentracing-spring-zipkin-web-starter</artifactId>
</dependency>

Gradle

classpath 'io.zipkin.reporter2:zipkin-reporter'
classpath 'io.zipkin.reporter2:zipkin-sender-okhttp3'
classpath 'io.opentracing.contrib:opentracing-spring-zipkin-web-starter'

2. Configure a SignalFx OpenTracing Reporter

By providing a bean of type ZipkinTracerCustomizer in our @Configuration class, we can explicitly set the Reporter on the Tracing.Builder object. SignalFx requires that the access token be provided as a X-SF-Token request header. To accomplish this we redefine a Reporter that explicitly adds the required header and then pass that into the Tracer.Builder via the ZipkinTracerCustomizer.

Defining the SignalFx Reporter

@Value("${opentracing.reporter.signalfx.ingest_url:https://ingest.signalfx.com/v1/trace}")
private String ingestUrl;

@Value("${opentracing.reporter.signalfx.access_token}")
private String accessToken;

private Reporter<Span> getSignalFxReporterInZipkinV2Format() {
    return AsyncReporter.create(getSignalFxHttpSender());
}

private Sender getSignalFxHttpSender() {
    // Setup the HttpSender to report to SignalFx with the access token
    OkHttpSender.Builder senderBuilder = OkHttpSender.newBuilder()
            .compressionEnabled(true)
            .endpoint(ingestUrl);

    senderBuilder.clientBuilder().addInterceptor(chain -> {
        Request request = chain.request().newBuilder()
            .addHeader("X-SF-Token", accessToken)
            .build();
        return chain.proceed(request);
    });

    return senderBuilder.build();
}

Customize the Tracer to use the SignalFx Reporter

@Bean
public ZipkinTracerCustomizer getCustomizerToAddSignalFxReporter() {
    ZipkinTracerCustomizer customizer = (Tracing.Builder builder) -> {
        builder.spanReporter(getSignalFxReporterInZipkinV2Format());
    };
    return customizer;
}

See SignalFxZipkinReporterConfiguration.java for the full source code.

3. Define Spring properties

spring.application.name is used as the service name and is picked up by core OpenTracing libraries. opentracing.reporter.signalfx.access_token is required to send data to SignalFx.

spring.application.name=Coin Flip
opentracing.reporter.signalfx.access_token=<<Access Token>>

Configuration References

Running the example project

Note: The example project uses Maven to build and package the Spring Boot application.

1. Download/clone the project from the git repository

$ git clone https://github.com/signalfx/tracing-examples.git
$ cd tracing-examples/jaeger-java-spring-boot-web

2. Compile and package the Spring Boot Application

$ mvn package

3. Start your Spring Boot Application

$ java -jar target/coin-flip-service-with-zipkin-0.0.1-SNAPSHOT.jar

4. Make requests to the application to generate spans

Open http://localhost:8080/flip in your browser.

Illustrated Concepts

Defining a subspan

The example application sends spans to SignalFx for 100% of requests. Most of the instrumentation is done by the Zipkin Spring library. The main application also wraps a function in a subspan called calculateOdds:

private boolean trueWithProbability(double probability) {
    try (Scope scope = tracer.buildSpan("calculateOdds").startActive(true)) {
        return Math.random() <= probability;
    }
}

Tagging the current Span

After the coin has been 'flipped', we tag the span so we can differentiate any telemetry between the outcome of the coin flip.

tracer.activeSpan().setTag("flipResult", flipResult);

See the example code for more context.