Salta al contenuto principale

07 - Backend Integration - Jaeger, Prometheus, and Grafana Setup

Jaeger (tracing backend), Prometheus (metrics), Grafana (visualization), integration, stack setup (Docker Compose, Kubernetes), example dashboards.

Cosa ne pensi di questo articolo?

07 - Backend Integration - Jaeger, Prometheus, and Grafana Setup
ObservabilityFoto:Atlantic AmbiencePexels

In Breve

Jaeger (tracing backend), Prometheus (metrics), Grafana (visualization), integration, stack setup (Docker Compose, Kubernetes), example dashboards.

Backend Integration: Jaeger, Prometheus e Grafana

Dopo aver instrumentato le applicazioni e configurato il Collector, il passo successivo e collegare i dati di telemetria ai backend di storage e visualizzazione. Lo stack open source più diffuso combina Jaeger per le tracce distribuite, Prometheus per le metriche e Grafana come layer di visualizzazione unificato. Insieme, questi strumenti formano un sistema di observability completo e production-ready.

In questo articolo configureremo l'intero stack da zero, dal deployment con Docker Compose alla creazione di dashboard Grafana che correlano tracce, metriche e log in un'unica interfaccia.

Cosa Imparerai in Questo Articolo

  • Setup completo di Jaeger per il tracing distribuito
  • Configurazione di Prometheus per la raccolta metriche
  • Dashboard Grafana per la visualizzazione unificata
  • Loki per la raccolta e query dei log
  • Correlazione tra tracce, metriche e log in Grafana
  • Deployment dello stack completo con Docker Compose

Lo Stack Completo con Docker Compose

Il modo più rapido per avviare l'intero stack di observability e usare Docker Compose. La configurazione seguente deploya tutti i componenti necessari con le connessioni già configurate:


# docker-compose.observability.yaml
version: "3.9"

services:
  # --- OpenTelemetry Collector ---
  otel-collector:
    image: otel/opentelemetry-collector-contrib:0.96.0
    command: ["--config=/etc/otel/config.yaml"]
    volumes:
      - ./otel-collector-config.yaml:/etc/otel/config.yaml
    ports:
      - "4317:4317"   # OTLP gRPC
      - "4318:4318"   # OTLP HTTP
      - "8889:8889"   # Prometheus metrics export
      - "13133:13133" # Health check
    depends_on:
      - jaeger
      - loki

  # --- Jaeger: Distributed Tracing Backend ---
  jaeger:
    image: jaegertracing/all-in-one:1.54
    environment:
      COLLECTOR_OTLP_ENABLED: "true"
      SPAN_STORAGE_TYPE: "badger"
      BADGER_EPHEMERAL: "false"
      BADGER_DIRECTORY_VALUE: "/badger/data"
      BADGER_DIRECTORY_KEY: "/badger/key"
    volumes:
      - jaeger_data:/badger
    ports:
      - "16686:16686" # Jaeger UI
      - "14250:14250" # gRPC collector

  # --- Prometheus: Metrics Backend ---
  prometheus:
    image: prom/prometheus:v2.50.0
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=30d"
      - "--web.enable-remote-write-receiver"
      - "--enable-feature=exemplar-storage"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    ports:
      - "9090:9090"

  # --- Loki: Log Aggregation ---
  loki:
    image: grafana/loki:2.9.4
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - ./loki-config.yaml:/etc/loki/local-config.yaml
      - loki_data:/loki
    ports:
      - "3100:3100"

  # --- Grafana: Visualization ---
  grafana:
    image: grafana/grafana:10.3.1
    environment:
      GF_SECURITY_ADMIN_USER: admin
      GF_SECURITY_ADMIN_PASSWORD: observability
      GF_FEATURE_TOGGLES_ENABLE: "traceqlEditor tempoSearch tempoBackendSearch"
    volumes:
      - ./grafana/provisioning:/etc/grafana/provisioning
      - grafana_data:/var/lib/grafana
    ports:
      - "3000:3000"
    depends_on:
      - prometheus
      - jaeger
      - loki

volumes:
  jaeger_data:
  prometheus_data:
  loki_data:
  grafana_data:
      

Jaeger: Tracing Distribuito

Jaeger e il backend open source più usato per il tracing distribuito. Originariamente sviluppato da Uber e ora progetto della CNCF, Jaeger riceve le tracce dal Collector, le archivia e fornisce una UI per la ricerca, visualizzazione e analisi delle tracce distribuite.

L'integrazione con OpenTelemetry e nativa: Jaeger accetta dati OTLP direttamente, eliminando la necessità di conversioni. La UI di Jaeger offre la vista waterfall per le singole tracce, la comparazione tra tracce e la ricerca per servizio, operazione, durata e tag.

Funzionalità Principali di Jaeger

Trace Search: ricerca tracce per servizio, operazione, durata min/max, tag e time range. Permette di trovare rapidamente le richieste problematiche.

Waterfall View: visualizzazione dettagliata di ogni span nella traccia, con tempi, attributi, eventi e relazioni parent-child.

Trace Comparison: confronto side-by-side di due tracce per identificare differenze nel comportamento tra una richiesta veloce e una lenta.

Service Dependencies: mappa automatica delle dipendenze tra servizi, derivata dalle tracce raccolte.

Prometheus: Raccolta Metriche

Prometheus e il sistema di monitoring e alerting open source standard per le metriche. Usa un modello pull (scraping) per raccogliere metriche da endpoint HTTP, supporta un linguaggio di query potente (PromQL) e si integra nativamente con Grafana per la visualizzazione.


# prometheus.yml - Configurazione Prometheus
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "/etc/prometheus/rules/*.yml"

scrape_configs:
  # Scraping del Collector OTel (metriche esportate)
  - job_name: "otel-collector"
    static_configs:
      - targets: ["otel-collector:8889"]
    scrape_interval: 10s

  # Metriche interne del Collector
  - job_name: "otel-collector-internal"
    static_configs:
      - targets: ["otel-collector:8888"]

  # Scraping applicazioni con endpoint /metrics
  - job_name: "applications"
    kubernetes_sd_configs:
      - role: pod
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
        action: keep
        regex: true
      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_port]
        action: replace
        target_label: __address__
        regex: (.+)
        replacement: "${1}:${2}"

  # Scraping Jaeger
  - job_name: "jaeger"
    static_configs:
      - targets: ["jaeger:14269"]

  # Scraping Prometheus stesso
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
      

Grafana: Visualizzazione Unificata

Grafana e il layer di visualizzazione che unifica tracce, metriche e log in un'unica interfaccia. Supporta nativamente Jaeger, Prometheus e Loki come data source, permettendo di creare dashboard che correlano tutti i segnali di telemetria.


# grafana/provisioning/datasources/datasources.yml
apiVersion: 1
datasources:
  # Prometheus per le metriche
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    jsonData:
      exemplarTraceIdDestinations:
        - name: traceID
          datasourceUid: jaeger
      httpMethod: POST

  # Jaeger per le tracce
  - name: Jaeger
    type: jaeger
    access: proxy
    url: http://jaeger:16686
    uid: jaeger
    jsonData:
      tracesToLogsV2:
        datasourceUid: loki
        filterByTraceID: true
        filterBySpanID: true
      tracesToMetrics:
        datasourceUid: Prometheus

  # Loki per i log
  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100
    uid: loki
    jsonData:
      derivedFields:
        - datasourceUid: jaeger
          matcherRegex: "trace_id=(\\w+)"
          name: TraceID
          url: "${__value.raw}"
      

Correlazione tra Segnali in Grafana

Il vero potere di Grafana emerge quando i tre data source sono configurati per la correlazione. Questo significa poter navigare da una metrica a una traccia, da una traccia ai log, e viceversa, in un flusso di debug continuo.

Flusso di Correlazione in Grafana

Dashboard metriche: vedi un picco nella latenza P99 → clic su "Exemplar" nel grafico → apertura della traccia in Jaeger → identifichi lo span lento (payment-gateway) → clic su "View Logs" → apertura log filtrati in Loki con il trace_id → trovi il messaggio di errore "connection timeout to payment provider".

Questo flusso trasforma il debugging da ore a minuti.

Loki: Aggregazione dei Log

Loki e il sistema di aggregazione log di Grafana, progettato per essere cost-effective e semplice da operare. A differenza di Elasticsearch, Loki indicizza solo le label (metadata), non il contenuto completo dei log, riducendo drasticamente i costi di storage e la complessità operativa.


# loki-config.yaml
auth_enabled: false

server:
  http_listen_port: 3100

common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2024-01-01
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h
  max_query_series: 500
  max_query_parallelism: 2

analytics:
  reporting_enabled: false
      

Query Essenziali per ogni Backend

  • Jaeger: ricerca per service, operation, min/max duration, tags (es. error=true)
  • Prometheus (PromQL): rate(http_requests_total[5m]), histogram_quantile(0.99, ...)
  • Loki (LogQL): {service="order-service"} |= "error" | json | trace_id != ""
  • Grafana Explore: split view per confrontare metriche e tracce side-by-side

Conclusioni e Prossimi Passi

Lo stack Jaeger + Prometheus + Loki + Grafana fornisce un sistema di observability completo, open source e production-ready. La chiave del successo e la correlazione: configurare i data source in Grafana per navigare fluidamente tra metriche, tracce e log, trasformando il debugging da un processo manuale e lungo a un flusso guidato e rapido.

Docker Compose e ideale per sviluppo e testing, mentre in produzione lo stack viene deployato su Kubernetes con Helm charts dedicati (jaeger-operator, kube-prometheus-stack, loki-stack).

Nel prossimo articolo approfondiremo la context propagation, analizzando come correlare log e tracce tramite trace ID, il protocollo W3C Baggage per il trasporto di metadata tra servizi, e i pattern per una correlazione efficace tra tutti i segnali.

Domande frequenti

Come funziona la combinazione di Jaeger, Prometheus e Grafana per creare un sistema di observability completo?

Questi strumenti formano un sistema di observability completo e production-ready, in cui Jaeger gestisce le tracce distribuite, Prometheus raccoglie le metriche e Grafana fornisce la visualizzazione unificata.

Qual è il vantaggio dell'integrazione nativa di OpenTelemetry con Jaeger?

L'integrazione nativa di OpenTelemetry con Jaeger elimina la necessità di conversioni dei dati, rendendo più facile e veloce l'invio delle tracce a Jaeger.

Come funziona la correlazione tra segnali in Grafana?

La correlazione tra segnali in Grafana permette di navigare fluidamente tra metriche, tracce e log, trasformando il debugging da un processo manuale e lungo a un flusso guidato e rapido.

Qual è la differenza principale tra Loki e Elasticsearch per quanto riguarda l'aggregazione dei log?

Loki indicizza solo le label (metadata) dei log, non il contenuto completo, riducendo drasticamente i costi di storage e la complessità operativa.

Fonti e approfondimenti

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti