Building a Bridge: Connecting OpenTracing with OpenTelemetry

| | OpenTracing

This year at KubeCon EMEA, the OpenTracing and OpenCensus teams announced that the two projects were merging to form OpenTelemetry.

One of the main priorities for the merger is straightforward backwards compatibility with both OpenTracing and OpenCensus, via software bridges.

In this post, we’ll discuss the OpenTracing to OpenTelemetry bridge.

Backwards Compatible — from Day One

By joining two similar-yet-not-identical projects, OpenTelemetry aims to reduce confusion for developers and make robust, portable telemetry a built-in feature of cloud-native software.

Again, one of the core aspects taken into account as part of the new OpenTelemetry effort has been to provide backwards compatibility with existing instrumentation code (libraries instrumentation, such as opentracing-django, as well as concrete application instrumentation).

At this moment, there is an ongoing effort for the Java scenario, but such bridges will be implemented for other languages as well.

In order to help with this, the OpenTracing bridge will take any OpenTelemetry Tracer and expose it as an OpenTracing Tracer:

io.opentracing.Tracer tracer = TracerShim.createTracerShim(openTelemetryTracer);

Once this is achieved, it’s possible to simply pass this instance to the initialization code:

static void startApplication () {
  io.opentelemetry.trace.Tracer tracer = ...;
  io.opentracing.Tracer openTracingTracer = TraceShim.createTracerShim(tracer);
  setUpExistingInstrumentation(openTracingTracer);
}

static void setUpExistingInstrumentation(io.opentracing.Tracer tracer) {
  // Set up the existing OkHttp instrumentation as usual.
  client = TracingInterceptor.addTracing(new OkHttpClient.Builder(), tracer);

  // ... and create Spans as usual too.
  Span initSpan = tracer.buildSpan("initialization").start();
  ...
}

Although this layer is currently being hosted in the OpenTelemetry Java repository, it will be released as a standalone library that users can later import.

Writing Code: OpenTracing vs. OpenTelemetry

Let’s look at some simple code. In our example, we have a database call to a hypothetical billing application.

Here is the code you would use to write using OpenTracing Java.

Span span = tracer.buildSpan("distributed-cache-lookup").start();
result = cache.Lookup(key);
span.setTag(“cache-hit”, result != null);
span.finish();

Now, here’s the code that you would write for that same call with OpenTelemetry.

Span span = tracer.buildSpan("distributed-cache-lookup").start();
result = cache.Lookup(key);
span.setTag(“cache-hit”, result != null);
span.finish();

It’s the same code! And the result? Nothing changes. OpenTracing concepts like spans and tags map one-to-one to those in OpenTelemetry.

Bridges are one part of our strategy to make it as easy as possible for existing OpenTracing and OpenCensus projects send data to OpenTelemetry based observability systems.

Initializing the OpenTelemetry Bridge with the LightStep Tracer

LightStep Tracers for the new OpenTelemetry API will be released on a language by language basis. After release it will be possible to use them with the bridge for existing OpenTracing instrumentation. Continuing with our example in Java, this will only require two steps:

1. Importing the OpenTracing Shim as a dependency in Maven/Gradle (single dependency).

<dependency>
    <groupId>io.opentracing</groupId>
    <artifactId>opentelemetry-shim</artifactId>
    <version>0.1.0</version>
</dependency>

2. Creating a Tracer Shim around the updated LS Tracer, and provide it to the existing OpenTracing-based instrumentation.

// Initialize the OpenTracing Tracer with LightStep's implementation
Tracer tracer = new com.lightstep.tracer.jre.JRETracer(new com.lightstep.tracer.shared.Options.OptionsBuilder().withAccessToken("{your_access_token}").build());
...
// Down the initialization, expose it as an OpenTracing Tracer instance:
io.opentracing.Tracer openTracingTracer = TraceShim.createTracerShim(tracer);

// Optionally register it as the OpenTracing GlobalTracer
io.opentracing.util.GlobalTracer.registerIfAbsent(openTracingTracer);

No more changes will be required for using OpenTracing-based instrumentation, as the Shim will be handling the logic behind the scenes.

OpenTelemetry Bridge: Technical Details

  • OpenTracing Java recently released the 0.33 version, which removes many deprecated members. This was done to ease the incoming migration from OpenTracing instrumentation code to the new OpenTelemetry API, as well as to simplify the requirements for the OpenTracing bridge.
  • The bridge layer (called Shim in the codebase) will internally automatically map logic in both sides. This includes Tags and Logs, which will be mapped to Attributes and Events in the new API. Tags with special meaning will also be translated. For example, the error tag (used, as it name implies, to declare an error happened) will be translated and used to set Span.setStatus(Status.UNKNOWN).
  • Currently such Shim layer has been tested with a port of the OpenTracing testbed, which covers a few advanced scenarios. Once this is fully achieved, testing will be done using a few instrumentation libraries (such as OkHttp or Mongo instrumentation). Further testing will happen mixing OpenTracing with OpenTelemetry instrumentation, making sure the entire pipe works smoothly.
  • The most important detail/challenge in the OpenTracing bridge is the support for Baggage, which in OpenTracing was part of SpanContext, whereas in OpenTelemetry exists as a standalone component (also currently known as Tags). A few alternatives will be tested in this case to make sure the OpenTracing behavior is kept.

Looking into the Not-So-Distant Future

So, what’s next?

OpenTelemetry is planning on reaching parity with Golang, Java, NodeJS, and Python for OpenTracing and OpenCensus by September 6th of this year.

To clarify, “parity” implies all of the following:

  • A set of interfaces which manifest the OpenTelemetry specification in each programming language
  • An SDK implementing OpenTelemetry specification
  • Backward compatibility with OpenTracing and OpenCensus
  • Metadata helpers for recording common operations defined in the OpenTelemetry semantic conventions
  • Tests which provide evidence of interoperability
  • Benchmarks which provide evidence of expected resource utilization
  • Documentation and getting started guide

It’s going to take a lot of work, but we’re making good progress.

Want to be a Part of OpenTelemetry?

Join us on Gitter or Github, or say hello on Twitter! We’re always looking for help building the future of high-quality, portable, built-in telemetry.

We're Hiring!

Add your talent and experience to our team of friendly, low-ego, and motivated people.