Distributed Tracing

Overview

Observability is an important aspect of microservice-oriented applications. One of the key ingredients for observability is distributed tracing.

It is necessary to provide additional precautions when an application writes a record to a database that is later processed by Debezium. The active trace is effectively demarcated by the write to the database. If you want to include Debezium data in your application tracer, you must pass the trace metadata to Debezium.

You can add tracing support to Debezium through the OpenTelemetry specification.

Installation

To enable traceability in Debezium, you must install the required OpenTelemetry API packages on your Kafka Connect cluster, together with the OpenTelemetry SDK.

There are three main methods for installing OpenTelemetry on Kafka Connect, each having its advantages:

Manual installation

Offers more control and customization.

Docker installation

Provides easier integration.

Strimzi installation

Presents a ready-to-use solution on Kubernetes that includes all of the necessary OpenTelemetry components.

Manual installation of OpenTelemetry

A manual installation provides greater control and customization.

Installing the OpenTelemetry API

Install the following packages to the Kafka Connect classpath:

You can download the OpenTelemetry packages directly from the Maven repository, or retrieve the packages by using the Maven dependency plugin to ensure version compatibility.

Using the Maven Dependency Plugin
  1. Create a POM file similar to the one in the following example. In your version of the file, specify the version of the OpenTelemetry package that you want to use.

    1. <?xml version="1.0"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    3. <modelVersion>4.0.0</modelVersion>
    4. <groupId>group.id</groupId>
    5. <artifactId>artifact-id</artifactId>
    6. <version>0.0.1</version>
    7. <properties>
    8. <version.opentelemetry.api>1.23.1</version.opentelemetry.api>
    9. <version.opentelemetry.kafka.clients.2.6>1.23.0-alpha</version.opentelemetry.kafka.clients.2.6>
    10. </properties>
    11. <dependencies>
    12. <dependency>
    13. <groupId>io.opentelemetry</groupId>
    14. <artifactId>opentelemetry-api</artifactId>
    15. <version>${version.opentelemetry.api}</version>
    16. </dependency>
    17. <dependency>
    18. <groupId>io.opentelemetry.instrumentation</groupId>
    19. <artifactId>opentelemetry-kafka-clients-2.6</artifactId>
    20. <version>${version.opentelemetry.kafka.clients.2.6}</version>
    21. </dependency>
    22. </dependencies>
    23. </project>
  2. In the directory that contains the pom.xml file, run the following command to download all dependencies (including transitives) to a specified directory (for example, ./lib)

    1. mvn dependency:copy-dependencies -DoutputDirectory=./lib

Installing the OpenTelemetry SDK

After you install the API, install the OpenTelemetry SDK. Install the OpenTelemetry SDK on your Kafka connect cluster by using the Java agent for automatic instrumentation.

Using Docker to install OpenTelemetry

Prefer this installation method if you want to use Docker for local development or testing.

The OpenTelemetry API dependencies are installed in the Debezium Kafka Connect container image. The JAR files are downloaded to a separate directory. By default, the JAR files are not added to the class path. To add the JAR files to the class path, set the environment variable ENABLE_OTEL to true. You must also install the OpenTelemetry Java agent.

Using Strimzi to install Open Telemetry

Strimzi provides a way to deploy an Apache Kafka cluster on Kubernetes.

The Strimzi Kafka image includes all of the necessary OpenTelemetry components.

If you want to view the OpenTelemetry components that are available in the Strimzi image, examine the compose file that is provided in the Debezium Outbox example.

Configuring OpenTelemetry

For information about how to configure OpenTelemetry, see the OpenTelemetry documentation.

Debezium was tested with a Debezium Kafka Connect image, and a Strimzi distribution that included the following configuration settings:

  • otel.traces.exporter=otlp

  • otel.propagators=tracecontext

ActivateTracingSpan SMT

The main implementation point of tracing in Debezium is ActivateTracingSpan SMT. In this case, the application writing to a database is responsible for providing the tracing span context. The writer must inject the span context into a java.util.Properties instance that is serialized and written to the database as a distinct field of the table.

If the span context is not provided then the SMT will create a new span. In this case, Debezium operations together with metadata will be traced but will not be connected to business transaction traces to enable end-to-end tracing.

When this SMT is invoked with a message then it will:

  • extract the parent span context if present in the message

  • create the event db-log-write span context with the start timestamp set to the database log write timestamp

  • insert fields from source block into the span as tags

  • create the processing debezium-read span as a child of db-log-write span with the start timestamp set to the processing time of the even

  • insert fields from envelope such as op into the processing span as tags

  • injects the processing span context into message headers

Kafka Producer tracing

Optionally it is possible to enable tracing at the Kafka producer level. If you enable tracing in the Kafka producer, when messages are written to the Kafka broker, the producer extracts the Debezium processing span context from the Kafka message headers, creates a new child span, and then records information about the write operation to the broker. Then it injects the new span into the message headers so a consumer of the message can restore the trace and resume end-to-end tracing.

The interceptor cannot propagate the traceability context if the Kafka instrumentation is enabled. The interceptor simply propagates the traceability context before delegating the instrumentation to the OpenTelemetry SDK.

Enabling end-to-end traceability

  1. Download and install the debezium-interceptor to the Kafka Connect classpath.

  2. Disable the automatic OpenTelemetry instrumentation at the Kafka producer and consumer by setting the value of otel.instrumentation.common.default-enabled to false.

Configuration options

Configuration property

Type

Default

    tracing.span.context.field

    The name of the field containing span context.

    The sender must write the span context into the database column as a serialized instance of java.util.Properties with injected span context.

string

tracingspancontext

    tracing.operation.name

    The operation name representing the Debezium processing span.

string

debezium-read

    tracing.with.context.field.only

    Only events that have serialized context field should be traced.

    If set to true then tracing span will be created only for events with associated tracing span context field. If set to false then the tracing span is created for all incoming events regardless of having associated span context.

boolean

false

Outbox Extension

The Debezium Quarkus extension for implementing the outbox pattern provides the additional functionality necessary for tracing context propagation out-of-the-box. Specifically, it provides the tracingspancontext field in the outbox table, which is used for passing the tracing span context from a service using the outbox extension to the Debezium connector.

When an outbox event is emitted, the extension will:

  • create a new outbox-write span as a child of current active span

  • inject the span context into that java.util.Properties instance that is serialized into the tracingspancontext column

  • write the record into the database

The tracing integration in the outbox extension is automatically enabled if the quarkus-opentelemetry extension is present. If you want to disable tracing support for the outbox extension despite the presence of the quarkus-opentelemetry extension, set the option quarkus.debezium-outbox.tracing.enabled=false in the Quarkus application.properties file.

Event Router SMT

The Event Router SMT acts as an Outbox extension counterpart, it executes the same steps as the ActivateTracingSpan SMT, and is used instead of it.