Using OpenTelemetry to send traces to Jaeger V2
Dapr supports writing traces using the OpenTelemetry (OTLP) protocol, and Jaeger V2 natively supports OTLP, allowing Dapr to send traces directly to a Jaeger V2 instance. This approach is recommended for production to leverage Jaeger V2’s capabilities for distributed tracing.
Configure Jaeger V2 in self-hosted mode
Local setup
The simplest way to start Jaeger is to run the pre-built, all-in-one Jaeger image published to DockerHub and expose the OTLP port:
docker run --rm --name jaeger \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 5778:5778 \
-p 9411:9411 \
cr.jaegertracing.io/jaegertracing/jaeger:2.11.0
Next, create the following config.yaml file locally:
Note: Because you are using the Open Telemetry protocol to talk to Jaeger, you need to fill out the
otelsection of the tracing configuration and set theendpointAddressto the address of the Jaeger container.
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: tracing
namespace: default
spec:
tracing:
samplingRate: "1"
stdout: true
otel:
endpointAddress: "localhost:4317"
isSecure: false
protocol: grpc
To launch the application referring to the new YAML configuration file, use
the --config option. For example:
dapr run --app-id myapp --app-port 3000 node app.js --config config.yaml
View traces
To view traces in your browser, go to http://localhost:16686 to see the Jaeger UI.
Configure Jaeger V2 on Kubernetes
The following steps show you how to configure Dapr to send distributed tracing data directly to a Jaeger V2 instance deployed using the OpenTelemetry Operator with in-memory storage.
Prerequisites
Set up Jaeger V2 with the OpenTelemetry Operator
Jaeger V2 can be deployed using the OpenTelemetry Operator for simplified management and native OTLP support. The following example configures Jaeger V2 with in-memory storage.
Note on Storage Backends: This example uses in-memory storage (
memstore) for simplicity, suitable for development or testing environments as it stores up to 100,000 traces in memory. For production environments, consider configuring a persistent storage backend like Cassandra or Elasticsearch to ensure trace data durability.
Installation
Install cert-manager to manage certificates:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.1/cert-manager.yaml -n cert-managerVerify that all resources in the
cert-managernamespace are ready.Install the OpenTelemetry Operator:
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yamlConfirm that all resources in the
opentelemetry-operator-systemnamespace are ready.Deploy a Jaeger V2 instance with in-memory storage: Apply the following configuration to create a Jaeger V2 instance:
apiVersion: opentelemetry.io/v1beta1 kind: OpenTelemetryCollector metadata: name: jaeger-inmemory-instance namespace: observability spec: image: jaegertracing/jaeger:latest ports: - name: jaeger port: 16686 config: service: extensions: [jaeger_storage, jaeger_query] pipelines: traces: receivers: [otlp] exporters: [jaeger_storage_exporter] extensions: jaeger_query: storage: traces: memstore jaeger_storage: backends: memstore: memory: max_traces: 100000 receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 exporters: jaeger_storage_exporter: trace_storage: memstoreApply it with:
kubectl apply -f jaeger-inmemory.yaml -n observability
Set up Dapr to send traces to Jaeger V2
Create a Dapr configuration file to enable tracing and export the sidecar traces directly to the Jaeger V2 instance.
Create a configuration file (e.g.,
tracing.yaml) with the following content, updating thenamespaceandotel.endpointAddressto match your Jaeger V2 instance:apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: tracing namespace: order-system spec: tracing: samplingRate: "1" otel: endpointAddress: "jaeger-inmemory-instance-collector.observability.svc.cluster.local:4317" isSecure: false protocol: grpcApply the configuration:
kubectl apply -f tracing.yaml -n order-system
Deploy your app with tracing enabled
Apply the tracing Dapr configuration by adding a dapr.io/config annotation to the application deployment that you want to enable distributed tracing for, as shown in the following example:
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
...
template:
metadata:
...
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "MyApp"
dapr.io/app-port: "8080"
dapr.io/config: "tracing"
You can register multiple tracing exporters at the same time, and the tracing logs are forwarded to all registered exporters.
That’s it! There’s no need to include the OpenTelemetry SDK or instrument your application code. Dapr automatically handles the distributed tracing for you.
View traces
To view Dapr sidecar traces, port-forward the Jaeger V2 service and open the UI:
kubectl port-forward svc/jaeger-inmemory-instance-collector 16686 -n observability
In your browser, go to http://localhost:16686 to see the Jaeger V2 UI.
