Skip to main content

How to set up Tracing with OpenTelemetry SDK

Atoti Server has been manually instrumented to provide precise and relevant feedback. However, having the generated traces reach your chosen endpoint requires a bit of work.

In this example, we will write a Spring configuration that sets up the Atoti Server tracing to send traces to a local Zipkin instance. The OpenTelemetry SDK will be used as our OpenTelemetry backend.

Prerequisites

This guides is written with the assumption that a Zipkin server at the address localhost:9411. Readers can easily create such a server from Docker with a command similar to docker run -d -p 9411:9411 openzipkin/zipkin.

Dependencies

We need the OpenTelemetry SDK, as well as a couple of necessary exporters. Import the following dependencies:

<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-zipkin</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-logging</artifactId>
</dependency>

General structure

The tracing setup is a good fit for a Spring configuration class, so that it can be swapped easily. Create a Spring configuration, make sure it is imported by Spring, and start writing a Bean with the OpenTelemetry type.

Creating the OpenTelemetry instance

An OpenTelemetry instance is made of three main parts: a tracer provider, a meter provider and a logger provider. We need to instantiate each of those to create our OpenTelemetry instance.

The Tracer Provider

For the tracer provider, we want it to export spans both to the console for debug purposes and to a Zipkin instance at the given URL. We also add the service name resource to easily distinguish spans from Atoti Server from other spans the Zipkin instance may collect.

String zipkinUrl = "http://localhost:9411/api/v2/spans";
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create()))
.addSpanProcessor(
BatchSpanProcessor.builder(ZipkinSpanExporter.builder().setEndpoint(zipkinUrl).build())
.build())
.addResource(
Resource.create(Attributes.of(AttributeKey.stringKey("service.name"), "Atoti Server")))
.build();

The Meter Provider

The OpenTelemetry Metrics API isn't currently used by Atoti Server, so we use a placeholder meter provider, that periodically prints metrics to the console:

SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder()
.registerMetricReader(PeriodicMetricReader.builder(LoggingMetricExporter.create()).build())
.build();

The Logger Provider

Similarly, this part of OpenTelemetry is unused for now, so we use a simple logger provider that redirects to the console.

SdkLoggerProvider sdkLoggerProvider = SdkLoggerProvider.builder()
.addLogRecordProcessor(SimpleLogRecordProcessor.create(SystemOutLogRecordExporter.create()))
.build();

Assembling the OpenTelemetry instance

Now that we have the main parts, we can construct the OpenTelemetry instance that we need.

return OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setMeterProvider(sdkMeterProvider)
.setLoggerProvider(sdkLoggerProvider)
.setPropagators(
ContextPropagators.create(
TextMapPropagator.composite(
W3CTraceContextPropagator.getInstance(),
W3CBaggagePropagator.getInstance())))
.build();

Use this as a bean in your application.

You should obtain a configuration class that should look quite like the OpenTelemetryTracingConfig from the sandbox.

Wiring the OpenTelemetry instance

Now that the OpenTelemetry instance is finished, we have to provide it to the Atoti Server tracing framework. Import the TracingConfig from our activepivot-server-spring module to take care of this step. The TracingConfig will autowire the OpenTelemetry bean and provide it to the tracing framework.

Check out the result

Everything is now setup to send application traces to Zipkin.
Go to your AtotiUI application and create a new Pivot Table with some hierarchies and measures. You can see traces in Zipkin related to the queries.

Going further

  • There are alternative ways to wire the constructed OpenTelemetry instance detailed here.
  • There are many other OpenTelemetry exporters one may want to use, listed there.