# 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 :
- 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 :
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.
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
Aucun commentaire pour le moment.