“Pourquoi la prod est lente ?” Sans observability, impossible de répondre. Voici comment implémenter les 3 piliers pour debug efficace en production.
Monitoring vs Observability
Monitoring (approche classique)
Savoir QUAND ça casse
→ Alertes sur métriques connues
→ "CPU > 80%" → Alerte
Limite : Ne répond pas au “Pourquoi ?”
Observability (approche moderne)
Comprendre POURQUOI ça casse
→ Investiguer comportements émergents
→ Corréler métriques + logs + traces
Exemple :
Alerte: API latency increased (+200ms)
Monitoring classique:
- "La latency est haute"
- Restart service ?
Observability:
- Trace montre : DB query lente
- Logs montrent : Lock contention
- Metrics montrent : Connexions DB saturées
→ Root cause: Missing index sur table users
Les 3 piliers
1. Métriques (Metrics)
Qu’est-ce que c’est ?
Valeurs numériques agrégées dans le temps.
http_requests_total{method="GET",status="200"} 45623
http_request_duration_ms{endpoint="/api/users",percentile="p95"} 145
Types de métriques :
# Counter : Toujours croissant
requests_total.inc()
# Gauge : Valeur instantanée
active_connections.set(42)
# Histogram : Distribution
request_duration.observe(0.145) # seconds
Exemple Prometheus :
from prometheus_client import Counter, Histogram, Gauge
# Counter
requests_total = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status']
)
# Histogram (auto-génère p50, p95, p99)
request_duration = Histogram(
'http_request_duration_seconds',
'HTTP request duration',
['endpoint']
)
# Gauge
active_users = Gauge(
'active_users_count',
'Number of active users'
)
# Usage
@app.route('/api/users')
def get_users():
with request_duration.labels(endpoint='/api/users').time():
requests_total.labels(method='GET', endpoint='/api/users', status='200').inc()
return fetch_users()
2. Logs
Qu’est-ce que c’est ?
Événements discrets avec contexte.
{
"timestamp": "2025-11-07T10:15:30Z",
"level": "error",
"message": "Database connection failed",
"user_id": "user_123",
"request_id": "req_456",
"error": "ETIMEDOUT",
"duration_ms": 5000
}
Structured logging (à faire) :
// ❌ Log string (impossible à parser)
console.log('User user_123 created order order_456');
// ✅ Structured log (parsable, searchable)
logger.info({
event: 'order_created',
user_id: 'user_123',
order_id: 'order_456',
total: 149.99,
currency: 'EUR'
});
Log levels :
logger.debug('Detailed debugging info'); // Dev only
logger.info('Normal operation'); // Info générale
logger.warn('Something unusual'); // Attention
logger.error('Error occurred'); // Erreur
logger.fatal('System crash'); // Critique
3. Traces distribuées
Qu’est-ce que c’est ?
Suivre une requête à travers plusieurs services.
User request → API Gateway → Auth Service → User Service → Database
└─────────────────── Trace ──────────────────────┘
Exemple trace :
Trace ID: abc123
├─ Span: api-gateway (120ms)
│ ├─ Span: auth-service (25ms)
│ │ └─ Span: redis-get (2ms)
│ └─ Span: user-service (85ms)
│ ├─ Span: db-query-users (60ms) ⚠️ SLOW
│ └─ Span: cache-set (3ms)
Implémentation OpenTelemetry :
import { trace } from '@opentelemetry/api';
const tracer = trace.getTracer('my-service');
async function getUser(userId: string) {
// Créer span
return tracer.startActiveSpan('get-user', async (span) => {
span.setAttribute('user.id', userId);
try {
// DB query (auto-instrumentée)
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
span.setAttribute('user.found', !!user);
span.setStatus({ code: SpanStatusCode.OK });
return user;
} catch (error) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR });
throw error;
} finally {
span.end();
}
});
}
Stack Observability moderne
Option 1 : Grafana Stack (Open Source)
Métriques: Prometheus + Grafana
Logs: Loki + Grafana
Traces: Tempo + Grafana
Total: ~$200/mois (self-hosted)
Architecture :
┌────────────┐
│Application │
└──┬──┬──┬───┘
│ │ │
│ │ └──────→ Tempo (Traces)
│ └─────────→ Loki (Logs)
└────────────→ Prometheus (Metrics)
↓
Grafana (Visualisation)
Option 2 : Datadog (SaaS)
All-in-one :
- Metrics
- Logs
- Traces
- APM
- Alerting
Coût: $15-$30/host/mois
Total: ~$500-2000/mois
Option 3 : Hybrid
Metrics: Prometheus (gratuit)
Logs & Traces: Datadog (payant)
Compromis coût/features
Correlation des 3 piliers
Exemple : Debug latency spike
1. Metrics : Identifier le problème
Dashboard Grafana :
http_request_duration_p95{endpoint="/api/orders"} spike 150ms → 800ms
2. Traces : Localiser le bottleneck
Trace pour requête lente :
├─ API Gateway: 5ms
├─ Auth: 3ms
└─ Orders Service: 785ms ⚠️
├─ Get user: 8ms
├─ Get products: 12ms
└─ Calculate shipping: 758ms ⚠️ ROOT CAUSE
3. Logs : Comprendre la cause
{
"timestamp": "...",
"level": "warn",
"service": "shipping-calculator",
"message": "External API timeout",
"external_api": "shipping-rates-api",
"timeout_ms": 5000,
"retries": 3
}
Root cause : API externe de shipping lente.
Fix :
- Ajouter cache pour shipping rates
- Réduire timeout 5s → 2s
- Fallback à rates par défaut
Dashboards essentiels
Dashboard 1 : RED Method (Services)
Rate: Requests/sec
Error: Error rate %
Duration: Latency (p50, p95, p99)
Grafana panel :
┌─────────────────────────────────────┐
│ Service: api-gateway │
├─────────────────────────────────────┤
│ Rate: 1,250 req/s │
│ Errors: 0.3% (🟢 < 1%) │
│ Duration: p95 = 145ms (🟢 < 500ms) │
└─────────────────────────────────────┘
Dashboard 2 : USE Method (Infrastructure)
Utilization: % resource used
Saturation: Queue depth
Errors: Error count
Exemple :
┌──────────────────────────────────┐
│ Host: prod-api-01 │
├──────────────────────────────────┤
│ CPU: 45% (🟢 < 80%) │
│ Memory: 68% (🟡 warning) │
│ Disk I/O: Queue depth 2 (🟢) │
│ Network: 125 Mbps (🟢) │
└──────────────────────────────────┘
Dashboard 3 : Business Metrics
┌────────────────────────────────────┐
│ E-commerce KPIs │
├────────────────────────────────────┤
│ Orders/hour: 142 (🟢 normal) │
│ Conversion: 3.2% (🟢 +0.1%) │
│ Cart abandonment: 68% (🟡 high) │
│ Revenue/hour: $12,450 │
└────────────────────────────────────┘
Alerting intelligent
Seuils statiques (simple)
# Alertmanager rule
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
for: 5m
annotations:
summary: "Error rate > 5% for 5 minutes"
Problème : False positives (traffic varie)
Seuils dynamiques (mieux)
# Anomaly detection basique
from statistics import mean, stdev
def is_anomaly(current_value, historical_values):
avg = mean(historical_values)
std = stdev(historical_values)
# Au-delà de 3 deviations standard
return abs(current_value - avg) > 3 * std
# Alerte si anomalie
if is_anomaly(current_latency, last_7_days_latency):
alert("Latency anomaly detected")
SLO-based alerting (optimal)
# Service Level Objective
slo:
target: 99.9% # 99.9% des requêtes < 500ms
# Budget d'erreur
error_budget: 0.1% # 0.1% peuvent être > 500ms
# Alerte si budget épuisé
- alert: SLOBudgetExhausted
expr: slo_error_budget_remaining < 0
annotations:
summary: "SLO budget exhausted, slow down deployments"
Cas réel : E-commerce Black Friday
Situation
- Black Friday : 10x traffic habituel
- Pas d’observability mature
Problème
11h00 : Site ralentit
11h15 : Checkout cassé
11h20 : Panique totale
Sans observability :
- 2 heures de debug
- $150k revenue perdu
Après : Stack Observability
Stack implémenté :
- Grafana Loki (logs)
- Tempo (traces)
- Prometheus (metrics)
- On-call avec PagerDuty
Black Friday suivant :
10h45 : Spike traffic détecté (metrics)
10h47 : Auto-scaling triggered
11h12 : DB slow query alert (trace)
11h15 : Index ajouté en 3 minutes
11h18 : Performance restored
Downtime : 0 minute Revenue : $2.4M (+60% vs année précédente)
Coûts et ROI
Coûts Stack Observability
Self-hosted (Grafana Stack) :
- Infrastructure : $200/mois
- Maintenance : 0.2 ETP (~$1k/mois)
- Total : ~$1,200/mois
SaaS (Datadog) :
- 20 hosts : $500/mois
- Logs : $800/mois
- Traces : $400/mois
- Total : ~$1,700/mois
ROI
Avant Observability :
- MTTR : 2-4 heures
- Incidents/mois : 8
- Coût incidents : ~$50k/an
Après Observability :
- MTTR : 15-30 minutes (-85%)
- Incidents/mois : 2 (-75%)
- Économie : ~$35k/an
ROI : Payé en 4-6 mois.
Getting Started (2 semaines)
Semaine 1 : Metrics
# 1. Setup Prometheus
docker run -p 9090:9090 prom/prometheus
# 2. Instrumenter app
pip install prometheus-client
# 3. Exposer metrics
from prometheus_client import make_wsgi_app
app.mount("/metrics", make_wsgi_app())
# 4. Dashboard Grafana
docker run -p 3000:3000 grafana/grafana
Semaine 2 : Logs + Traces
# Logs : Loki
docker run -p 3100:3100 grafana/loki
# Traces : Tempo
docker run -p 3200:3200 grafana/tempo
# Instrumenter app
pip install opentelemetry-api opentelemetry-sdk
Conclusion
Observability n’est pas un luxe.
C’est une nécessité :
- Réduire MTTR de 90%
- Comprendre comportements prod
- Anticiper problèmes
3 piliers à implémenter :
- Métriques (commencer ici)
- Logs (structured!)
- Traces (pour microservices)
Commencer simple :
- Prometheus + Grafana (semaine 1)
- Structured logging (semaine 2)
- Tracing si microservices (semaine 3-4)
Et vous, votre stack observability ?