Aller au contenu principal

Bonnes pratiques


1 - Naming Conventions

1.1 Métriques

# Format recommandé
<namespace>_<subsystem>_<name>_<unit>

# Exemples
http_requests_total
http_request_duration_seconds
node_memory_MemAvailable_bytes
process_cpu_seconds_total
RègleBonMauvais
Snake casehttp_requests_totalhttpRequestsTotal
Unité en suffixrequest_duration_secondsrequest_duration_ms
Base unitbytes pas kilobytesmemory_mb
_total pour counterserrors_totalerror_count

1.2 Labels

# Labels recommandés
http_requests_total{
service="api-gateway",
method="GET",
status="200",
endpoint="/api/users"
}

# Labels à éviter
http_requests_total{
request_id="abc123", # Cardinalité infinie
timestamp="2024-01-15", # Jamais en label
user_email="[email protected]" # PII
}

1.3 Logs

{
"timestamp": "2024-01-15T10:30:00.000Z",
"level": "INFO",
"service": "api-gateway",
"trace_id": "abc123",
"span_id": "def456",
"message": "Request processed",
"context": {
"user_id": "user-123",
"endpoint": "/api/orders",
"method": "POST",
"duration_ms": 150
}
}

2 - Cardinality Management

2.1 Le problème

2.2 Solutions

StratégieDescription
Limiter les labelsMax 5-7 labels par métrique
Éviter les IDsPas de request_id, user_id
BucketiserConvertir en ranges
Recording rulesPré-agréger
# Mauvais - cardinalité élevée
http_requests_total{user_id="..."}

# Bon - regroupement
http_requests_total{user_tier="premium"}

2.3 Vérification

# Compter les séries par métrique
count by (__name__) ({__name__=~".+"})

# Top métriques par cardinalité
topk(10, count by (__name__) ({__name__=~".+"}))

3 - Retention et Storage

3.1 Stratégie par type

DonnéeHotWarmColdDelete
Métriques7j30j90j1 an
Logs3j14j30j90j
Traces3j7j14j30j

3.2 Configuration Prometheus

# prometheus.yml
global:
scrape_interval: 15s

storage:
tsdb:
retention.time: 15d
retention.size: 50GB

3.3 Downsampling (Thanos)

# thanos-compact.yml
downsample:
resolution: 5m # Après 2 semaines
resolution: 1h # Après 1 mois

4 - Structured Logging

4.1 Format

// ❌ Mauvais
logger.info(`User ${userId} logged in from ${ip}`);

// ✅ Bon
logger.info('User logged in', {
user_id: userId,
ip_address: ip,
event: 'user.login'
});

4.2 Log Levels

LevelUsageExemple
ERRORErreur nécessitant attentionDB connection failed
WARNAnomalie non bloquanteRate limit approaching
INFOÉvénement businessOrder created
DEBUGDétails techniquesQuery executed

4.3 Correlation IDs

const { v4: uuidv4 } = require('uuid');

// Middleware Express
app.use((req, res, next) => {
req.correlationId = req.headers['x-correlation-id'] || uuidv4();
res.setHeader('x-correlation-id', req.correlationId);

// Ajouter à tous les logs
req.log = logger.child({ correlationId: req.correlationId });
next();
});

5 - Dashboard Design

5.1 Layout type

┌─────────────────────────────────────────────────────────────┐
│ FILTRES (Variables) │
├─────────────────────────────────────────────────────────────┤
│ Requests │ Errors │ Latency │ Saturation │ Uptime │
├─────────────────────────────────────────────────────────────┤
│ │
│ GRAPHIQUE PRINCIPAL │
│ (Request Rate + Errors) │
│ │
├──────────────────────────┬──────────────────────────────────┤
│ │ │
│ Latency Distribution │ Top Endpoints │
│ │ │
├──────────────────────────┴──────────────────────────────────┤
│ │
│ LOGS / EVENTS │
│ │
└─────────────────────────────────────────────────────────────┘

5.2 Principes

PrincipeDescription
Progressive disclosureGénéral → Détaillé
Drill-downClic pour détails
ContexteVariables pour filtrer
Alertes visiblesRouge = problème

6 - Alerting Best Practices

6.1 Symptômes vs Causes

# ❌ Alerte sur cause
- alert: HighCPU
expr: node_cpu_usage > 80%

# ✅ Alerte sur symptôme
- alert: HighLatency
expr: http_request_duration_seconds_p99 > 1

# ✅ Avec runbook
annotations:
runbook: "https://wiki/runbooks/high-latency"
possible_causes: "CPU, Memory, Database, Dependencies"

6.2 Multi-window Alerts

# Alerte avec multiple windows
- alert: HighErrorRate
expr: |
(
# Taux sur 5 minutes
sum(rate(http_errors_total[5m])) / sum(rate(http_requests_total[5m])) > 0.05
) and (
# Taux sur 1 heure aussi élevé
sum(rate(http_errors_total[1h])) / sum(rate(http_requests_total[1h])) > 0.02
)
for: 5m

6.3 Checklist

Pour chaque alerte:
- [ ] Symptôme, pas cause?
- [ ] Actionnable?
- [ ] Runbook linkté?
- [ ] Seuils basés sur données?
- [ ] For duration appropriée?
- [ ] Testée?

7 - Observability Maturity

7.1 Niveaux

NiveauCaractéristiques
0 - NonePas de monitoring
1 - BasicMétriques infra, alertes basiques
2 - MetricsMétriques app, dashboards
3 - LogsLogs centralisés, corrélation
4 - TracesDistributed tracing
5 - AdvancedSLOs, Error budgets, Auto-remediation

7.2 Checklist par niveau

level_1:
- [ ] Métriques CPU/Memory/Disk
- [ ] Alertes disponibilité
- [ ] Dashboard basique

level_2:
- [ ] Métriques applicatives
- [ ] Golden signals
- [ ] Dashboards service

level_3:
- [ ] Logs structurés
- [ ] Recherche centralisée
- [ ] Correlation IDs

level_4:
- [ ] OpenTelemetry
- [ ] Distributed tracing
- [ ] Service maps

level_5:
- [ ] SLIs/SLOs définis
- [ ] Error budgets
- [ ] Auto-scaling/remediation

8 - Cost Optimization

8.1 Stratégies

StratégieÉconomie
Sampling traces50-90%
Log level prod30-50%
Retention courteVariable
Recording rules20-40%
Compression30-50%

8.2 Sampling intelligent

# otel-collector-config.yaml
processors:
tail_sampling:
policies:
# Garder 100% des erreurs
- name: errors
type: status_code
status_code:
status_codes: [ERROR]
# Garder 100% des traces lentes
- name: slow
type: latency
latency:
threshold_ms: 1000
# 10% du reste
- name: default
type: probabilistic
probabilistic:
sampling_percentage: 10

Résumé

Dans ce chapitre, nous avons couvert :

  • Les conventions de nommage
  • La gestion de la cardinalité
  • Les stratégies de retention
  • Le structured logging
  • Le design de dashboards
  • Les bonnes pratiques alerting
  • La maturité observabilité
  • L'optimisation des coûts

Prochaine étape

Dans le prochain chapitre, nous mettrons en pratique avec des Exercices et Projets.

→ Chapitre suivant : Exercices et Projets


← Retour à la table des matières