Skip to content

Latest commit

 

History

History
170 lines (122 loc) · 5.35 KB

File metadata and controls

170 lines (122 loc) · 5.35 KB

Jaeger, Spring-boot and SignalFx

About

This example project demonstrates how to use Spring Boot, Jaeger, and SignalFx together. This example uses the Java Spring Jaeger Project and demonstrates how to configure the Java Spring Jaeger 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.opentracing.contrib</groupId>
    <artifactId>opentracing-spring-jaeger-web-starter</artifactId>
</dependency>

Gradle

classpath 'io.opentracing.contrib:opentracing-spring-jaeger-web-starter'

2. Configure a SignalFx OpenTracing Reporter

By providing a bean of type ReporterAppender in our @Configuration class, we can add a custom reporter to the list of Reporters used by Jaeger. The Jaeger Spring library allows for HTTP output but 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.

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 createSignalFxReporter() {
    // Setup the HttpSender to report to SignalFx with the access token
    OkHttpClient signalFxHttpClientWithAuthHeaders = new OkHttpClient.Builder()
        .addInterceptor(chain -> {
          Request request = chain.request().newBuilder()
            .addHeader("X-SF-Token", accessToken)
            .build();
          return chain.proceed(request);
        }).build();

    HttpSender.Builder senderBuilder = new HttpSender.Builder(ingestUrl)
        .withClient(signalFxHttpClientWithAuthHeaders);

    return new RemoteReporter.Builder()
        .withSender(senderBuilder.build())
        .build();
}

Appending the SignalFx Reporter

@Bean
public ReporterAppender getSignalFxReporterAppender() {
    return (Collection<Reporter> reporters) -> {
        reporters.add(createSignalFxReporter());
    };
}

See SignalFxJaegerReporterConfiguration.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>>

Optional Configuration

Sampling

By default the Jaeger library will sample 100% of requests if no other sampling strategies are defined, which works well for our example application. If this isn't desireable define a strategy by using the Jaeger Spring configuration options.

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-jaeger-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 Jaeger 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.