Retour à l'accueil

Pile OpenTelemetry Go : Tempo Prometheus Loki

L'article décrit le déploiement de la pile OpenTelemetry pour les applications Go avec Tempo, Prometheus et Loki. Il fournit docker-compose, configurations et code Go pour initialiser les providers. L'intégration dans Grafana permet les transitions entre métriques, traces et logs.

Pile OTel pour Go : guide de déploiement complet
Advertisement 728x90

# Déploiement de la pile OpenTelemetry pour Go : Traces, métriques et logs

La pile OpenTelemetry pour les applications Go collecte les traces dans Tempo, les métriques dans Prometheus et les logs dans Loki. L'application cliente app-1 envoie des requêtes au serveur app-2 via otel-collector. Grafana visualise toutes les données. La pile complète s'exécute avec docker-compose en utilisant une configuration minimale.

Configuration de Docker Compose

Services principaux : deux applications Go, otel-collector en tant que récepteur de télémétrie, backends Tempo/Prometheus/Loki et Grafana. Le réseau d'observabilité isole le trafic.

Ports principaux :

Google AdInline article slot
  • app-2 : 8080
  • otel-collector : 4317 (gRPC), 4318 (HTTP), 8889 (métriques)
  • Prometheus : 9090
  • Tempo : 3200
  • Loki : 3100
  • Grafana : 3000
services:
  app-1:
    build: ./app_1
    depends_on:
      otel-collector:
        condition: service_started
    networks:
      - observability
  app-2:
    build: ./app_2
    ports:
      - "8080:8080"
    networks:
      - observability
  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    ports:
      - "4318:4318"
      - "4317:4317"
      - "8889:8889"
    volumes:
      - ./configs/otel-collector-config.yaml:/etc/otelcol/config.yaml:ro
    networks:
      - observability
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./configs/prometheus.yml:/etc/prometheus/prometheus.yml:ro
    networks:
      - observability
  tempo:
    image: grafana/tempo:2.7.0
    ports:
      - "3200:3200"
    volumes:
      - ./configs/tempo-config.yaml:/etc/tempo/tempo.yaml
    networks:
      - observability
  loki:
    image: grafana/loki:3.3.2
    ports:
      - "3100:3100"
    volumes:
      - ./configs/loki-config.yaml:/etc/loki/local-config.yaml:ro
    networks:
      - observability
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - ./configs/grafana/datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml:ro
    networks:
      - observability
networks:
  observability:
    driver: bridge

Configuration de Tempo pour les traces

Tempo reçoit OTLP via gRPC (4317) et HTTP (4318). Les blocs de traces sont compactés avec une rétention de 30 min. trace_idle_period de 5 s assure une visibilité rapide dans l'interface utilisateur.

server:
  http_listen_port: 3200
  grpc_listen_port: 9095
distributor:
  receivers:
    otlp:
      protocols:
        grpc:
          endpoint: "0.0.0.0:4317"
ingester:
  trace_idle_period: 5s
  max_block_duration: 30m
storage:
  trace:
    backend: local
    local:
      path: /var/tempo/traces
compactor:
  compaction:
    block_retention: 30m

Prometheus et règles d'alerte

Les métriques sont collectées depuis otel-collector:8889 toutes les 60 s. Les règles d'alerte suivent la latence P95 > 2000 ms et le taux d'erreur > 5 %.

global:
  scrape_interval: 60s
scrape_configs:
  - job_name: "otel-collector"
    static_configs:
      - targets: ["otel-collector:8889"]

Exemple de règles :

Google AdInline article slot
groups:
  - name: app1-service-alerts
    rules:
      - alert: App1LatencyHigh
        expr: histogram_quantile(0.95, sum by (le) (rate(app_1_requests_latency_ms_bucket[5m]))) > 2000
        for: 3m
        labels:
          severity: warning
  - name: app2-service-alerts
    rules:
      - alert: App2HighErrorRate
        expr: rate(app_2_requests_total{status="failed"}[5m]) / rate(app_2_requests_total[5m]) > 0.05
        for: 2m
        labels:
          severity: critical

Configuration de Loki pour les logs

Les logs sont stockés dans le système de fichiers avec le schéma TSDB v13. Indexation par périodes de 24 h. Métadonnées structurées activées.

auth_enabled: false
server:
  http_listen_port: 3100
common:
  path_prefix: /tmp/loki
  storage:
    filesystem:
      chunks_directory: /tmp/loki/chunks
schema_config:
  configs:
    - from: 2020-10-24
      store: tsdb
      schema: v13
      index:
        period: 24h
limits_config:
  allow_structured_metadata: true

Intégration dans Grafana

Les sources de données lient métriques→traces→logs :

  • Prometheus exemplarTraceIdDestinations
  • Loki derivedFields par traceID
  • Tempo serviceMap et tracesToLogsV2

Initialisation d'OTel dans le client Go

La fonction InitOTel crée des fournisseurs pour tous les signaux avec des attributs de ressource. Échantillonnage de 10 % pour les traces, batching pour l'export.

Google AdInline article slot
func InitOTel(ctx context.Context, serviceName string) (*log.LoggerProvider, func(context.Context) error) {
    ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
    defer cancel()

    res := resource.NewWithAttributes(
       semconv.SchemaURL,
       semconv.ServiceName(serviceName),
       semconv.ServiceVersion("1.0.0"),
    )

    // Tracing
    traceExp, err := otlptracegrpc.New(ctx,
       otlptracegrpc.WithEndpoint("otel-collector:4317"),
       otlptracegrpc.WithInsecure(),
    )
    tracerProvider := sdktrace.NewTracerProvider(
       sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.1))),
       sdktrace.WithBatcher(traceExp),
       sdktrace.WithResource(res),
    )
    otel.SetTracerProvider(tracerProvider)

    // Metrics
    metricExp, err := otlpmetricgrpc.New(ctx,
       otlpmetricgrpc.WithEndpoint("otel-collector:4317"),
       otlpmetricgrpc.WithInsecure(),
    )
    meterProvider := sdkmetric.NewMeterProvider(
       sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExp, sdkmetric.WithInterval(10*time.Second))),
       sdkmetric.WithResource(res),
    )
    otel.SetMeterProvider(meterProvider)

    // Logs
    logExp, _ := otlploggrpc.New(ctx,
       otlploggrpc.WithEndpoint("otel-collector:4317"),
       otlploggrpc.WithInsecure(),
    )
    logProvider := log.NewLoggerProvider(
       log.WithProcessor(log.NewBatchProcessor(logExp)),
       log.WithResource(res),
    )

    return logProvider, func(ctx context.Context) error {
       // shutdown logic
       return nil
    }
}

Points clés

  • Pile OTel complète : traces (Tempo), métriques (Prometheus), logs (Loki) intégrés via otel-collector
  • Instrumentation Go : otelhttp.Transport, otelslog.Handler, métriques counter/histogram
  • Intégration native Grafana : transitions des métriques→traces→logs par traceID
  • Performances : trace_idle_period 5 s, échantillonnage 10 %, lecteur périodique 10 s
  • Alerte : latence P95 > 2000 ms, taux d'erreur > 5 %

— Editorial Team

Advertisement 728x90

Lire ensuite