DEV Community

丁久
丁久

Posted on • Originally published at dingjiu1989-hue.github.io

Tracing Tools: Jaeger, Zipkin, Tempo, OpenTelemetry Collector

This article was originally published on AI Study Room. For the full version with working code examples and related articles, visit the original post.

Tracing Tools: Jaeger, Zipkin, Tempo, OpenTelemetry Collector

Introduction

Distributed tracing is essential for understanding request flows across microservices. When a single user request hits 10-50 services, traditional logging cannot show you the full picture. Tracing captures the causality chain: which service called which, how long each call took, and where failures occurred. This article covers Jaeger, Zipkin, Grafana Tempo, and the OpenTelemetry Collector.

OpenTelemetry Collector

The foundation for modern observability — receives, processes, and exports telemetry data:

# otel-collector-config.yaml

receivers:

  otlp:

    protocols:

      grpc:

        endpoint: 0.0.0.0:4317

      http:

        endpoint: 0.0.0.0:4318

processors:

  batch:

    timeout: 1s

    send_batch_size: 1024

  memory_limiter:

    check_interval: 1s

    limit_mib: 512

  attributes:

    actions:

      - key: environment

        value: production

        action: insert

  filter:

    error_mode: ignore

    traces:

      span:

        - 'attributes["http.method"] == "OPTIONS"'

  # Sampling for cost control

  probabilistic_sampler:

    sampling_percentage: 10  # Only send 10% of traces

exporters:

  otlp:

    endpoint: jaeger:4317

    tls:

      insecure: true

  prometheus:

    endpoint: 0.0.0.0:8889

  debug:

    verbosity: detailed

service:

  pipelines:

    traces:

      receivers: [otlp]

      processors: [memory_limiter, batch, attributes, filter, probabilistic_sampler]

      exporters: [otlp, debug]

    metrics:

      receivers: [otlp]

      processors: [batch]

      exporters: [prometheus]

# Run the collector

otelcol --config otel-collector-config.yaml

# Run as Docker

docker run -v $(pwd)/otel-collector-config.yaml:/etc/otel/config.yaml otel/opentelemetry-collector-contrib
Enter fullscreen mode Exit fullscreen mode

Key features: Vendor-agnostic data collection, tail-based sampling, attribute enrichment, batch processing, multi-destination export, service graph computation.

Jaeger

Uber's distributed tracing system, now a CNCF graduated project:

# docker-compose.yml

services:

  jaeger:

    image: jaegertracing/all-in-one:latest

    environment:

      - COLLECTOR_OTLP_ENABLED=true

    ports:

      - "16686:16686"  # UI

      - "4317:4317"    # OTLP gRPC

      - "4318:4318"    # OTLP HTTP

# Python instrumentation with OpenTelemetry

from opentelemetry import trace

from opentelemetry.sdk.trace import TracerProvider

from opentelemetry.sdk.trace.export import BatchSpanProcessor

from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

from opentelemetry.instrumentation.flask import FlaskInstrumentor

from opentelemetry.instrumentation.requests import RequestsInstrumentor

# Set up tracing

provider = TracerProvider()

processor = BatchSpanProcessor(OTLPSpanExporter(

    endpoint="http://jaeger:4317",

    insecure=True,

))

provider.add_span_processor(processor)

trace.set_tracer_provider(provider)

# Auto-instrument libraries

FlaskInstrumentor().instrument()

RequestsInstrumentor().instrument()

# Manual instrumentation

from opentelemetry import trace

tracer = trace.get_tracer(__name__)

@app.route("/api/orders/<order_id>")

def get_order(order_id):

    with tracer.start_as_current_span("process_order") as span:

        span.set_attribute("order.id", order_id)

        span.set_attribute("order.value", 99.50)

        with tracer.start_as_current_span("validate_cache") as child:

            cached = cache.get(order_id)

            child.set_attribute("cache.hit", cached is not None)

        with tracer.start_as_current_span("query_database") as db_span:

            order = db.query("SELECT * FROM orders WHERE id = ?", order_id)

            db_span.set_attribute("db.rows", 1)

        return order
Enter fullscreen mode Exit fullscreen mode

Key features: Rich UI with trace search and filtering, service dependency graph, deep span detail view, comparison view for similar traces, OTLP native support.

Tempo (Grafana Tempo)

Grafana's tracing backend with object storage for cost-effective retention:

# tempo-config.yaml

server:

  http_listen_port: 3200

distributor:

  receivers:

    otlp:

      protocols:

        grpc:

          endpoint: 0.0.0.0:4317

ingester:

  trace_idle_period: 10s

  max_block_duration: 5m

storage:

  trace:

    backend: s3

    s3:

      bucket: grafana-tempo-data

      endpoint: s3.us-east-1.amazonaws.com

      access_key: ${AWS_ACCESS_KEY_ID}

      secret_key: ${AWS_SECRET_ACCESS_KEY}

    pool:
Enter fullscreen mode Exit fullscreen mode

Read the full article on AI Study Room for complete code examples, comparison tables, and related resources.

Found this useful? Check out more developer guides and tool comparisons on AI Study Room.

Top comments (0)