Loger et tracer des événements
Loger et tracer des événements
1) Objectif et cadre
Les logs et les tracés sont les fondements de l'observation.
Les logs répondent à « ce qui s'est passé » et « avec quel contexte ».
Les tracés répondent à « où et pourquoi lentement/par erreur » dans le chemin de requête distribué.
- Structured by default (JSON); Trace-first : Chaque journal du chemin chaud est lié à 'trace _ id '/' span _ id'.
- Minimum de bruit, maximum de signal : niveaux, sampling, anti-cardinalité.
- Sécurité et vie privée : masquage, édition, délimitation d'accès.
- Diagrammes de logs et d'événements versionnés.
2) Taxonomie des événements
Séparez les flux et les index comme prévu :1. Logs techniques (runtime, erreurs, temporisations réseau, retraits).
2. Les événements d'affaires (enregistrement, dépôt, pari, retrait, KYC-étape) sont adaptés à l'analyse des produits et aux incidents sur les voies « monétaires ».
3. L'audit (qui/quand a changé : configis, accès, drapeaux, limites) est un journal immuable.
4. Sécurité (authentification, escalade des privilèges, drapeaux de sanctions/RER).
5. Infrastructure (K8s événements, autoscaling, HPA/VPA, nœuds/disque/réseau).
Pour chaque flux, des règles distinctes de rétention, d'indexation et d'accès.
3) Logue structurelle (référence JSON)
json
{
"ts": "2025-11-03T14:28:15.123Z",
"level": "ERROR",
"service": "payments-api",
"env": "prod",
"region": "eu-central-1",
"trace_id": "8a4f0c2e9b1f42d7",
"span_id": "c7d1f3a4b8b6e912",
"parent_span_id": "a1b2c3d4e5f60789",
"logger": "withdraw.handler",
"event": "psp_decline",
"msg": "PSP declined transaction",
"http": { "method": "POST", "route": "/withdraw", "status": 502, "latency_ms": 842 },
"user": { "tenant_id": "t_9f2", "user_key": "hash_0a7c", "vip_tier": 3 },
"payment": { "psp": "acme", "amount": 120.50, "currency": "EUR", "idempotency_key": "u123:wd:7845" },
"safe": true, // пройдена проверка на секреты
"version": "1.14.2", // версия сервиса (SemVer)
"build": "sha-1f2a3b4",
"kubernetes": { "pod": "payments-7cbdf", "node": "ip-10-0-2-41" }
}
Exigences : schéma plat + pièces jointes par domaine, champs obligatoires ('ts, level, service, bou, trace_id, msg'), valeurs numériques - nombres, non-lignes.
4) Niveaux, cardinalité et volume
Niveaux : 'DEBUG' (pas dans la vente), 'INFO' (faits commerciaux), 'WARN' (anomalies),' ERROR '(erreurs),' FATAL '.
Cardinalité : éviter les clés arbitraires/étiquettes dynamiques. Pas d'ID.
Sampling des logs : rate-limit messages répétés ; incluez « DEBUG » seulement scopé et dans le temps (feature flag).
Idempotence : Loger 'idempotency _ key' pour supprimer les duplications d'événements par les consommateurs.
5) Vie privée et sécurité
Masquer les PII/secrets sur les agents (Fluent Bit/Vector) : cartes de masquage par clés ('email', 'card', 'token', 'autorisation').
Hachez 'user _ key', ne conservez que le contexte requis (pays, niveau KYC, VIP-tier).
Séparez les entrepôts : chauds (recherche en ligne) et froids (archives sans PII/c dans un contexte réduit).
Audit - append-only, stockage WORM, accès uniquement selon le principe least privilège.
6) Traçage : Normes et contexte
W3C Trace Context : titres 'traceparent '/' tracestate', plus baggage pour les clés sécurisées (par exemple, 'tenant _ id', 'region').
Association des métriques et des tracés : Exemplars - Passez 'trace _ id'aux points semplés des histogrammes (accélère RCA).
Sampling : sampling de base 1-5 % + dynamique « sur erreur/p95 lent » jusqu'à 100 % pour les requêtes problématiques.
Liens : pour les files d'attente/sags asynchrones, liez les spans via 'liens' et pas seulement via 'parent'.
7) Collecte et routage
Agents : Bit/vecteur fluent pour les logs ; Exportation OTLP vers OpenTelemetry Collector.
Collecteur : passerelle centrale (batch/bou/filter/routing).
App → (OTLP logs/traces/metrics) → OTel Collector
→ logs: redact → route(security audit tech biz) → hot index / cold archive
→ traces: tail_sampling(errors p95>threshold) → APM backend
→ metrics: Prometheus exporter (for SLO/alerts)
Collecteur OTel (fragment) :
yaml processors:
batch: {}
attributes:
actions:
- key: env value: prod action: insert filter/logs:
logs:
include:
match_type: strict resource_attributes:
- key: service.name value: payments-api exporters:
otlp/traces: { endpoint: "apm:4317", tls: { insecure: true } }
loki: { endpoint: "http://loki:3100/loki/api/v1/push" }
prometheus: {}
service:
pipelines:
logs: { receivers: [otlp], processors: [attributes,batch], exporters: [loki] }
traces: { receivers: [otlp], processors: [batch], exporters: [otlp/traces] }
metrics: { receivers: [otlp], processors: [batch], exporters: [prometheus] }
8) Instrumentation : exemples de SDK
8. 1 Node. js (Pino + OTel)
js import pino from "pino";
import { context, trace } from "@opentelemetry/api";
const logger = pino({ level: process.env.LOG_LEVEL "info" });
function log(info) {
const span = trace.getSpan(context.active());
const base = span? { trace_id: span.spanContext().traceId, span_id: span.spanContext().spanId }: {};
logger.info({...base,...info });
}
// пример log({ event: "deposit.created", amount: 50, currency: "EUR", user: { user_key: "hash_0a7c" } });
8. 2 Java (SLF4J + OTel)
java
MDC.put("trace_id", Span.current().getSpanContext().getTraceId());
MDC.put("span_id", Span.current().getSpanContext().getSpanId());
log.info("psp_response status={} latency_ms={}", status, latency);
8. 3 Python (structlog + OTel)
python import structlog from opentelemetry import trace log = structlog.get_logger()
def log_json(event, kwargs):
span = trace.get_current_span()
ctx = {}
if span and span.get_span_context().is_valid:
ctx = {"trace_id": span.get_span_context().trace_id, "span_id": span.get_span_context().span_id}
log.msg(event=event, ctx, kwargs)
8. 4 NGINX → trace des titres
nginx proxy_set_header traceparent $http_traceparent;
proxy_set_header tracestate $http_tracestate;
9) Logs comme signal pour alerts et auto-action
Agrégez et corrélez les motifs erronés ('psp _ decline', 'fraud _ flag') avec SLO.
Alerts sur pattern-rate : "5xx par/withdraw> 0. 5 % pour 10m', « fraud_flag spike> + 200 % de la base ».
Auto-action : dans le log'withdrawals _ manual _ mode = true ', activez kill-switch via la plate-forme des drapeaux.
rate(count_over_time({service="payments-api", level="ERROR", event="psp_decline"}[5m])) > 5
10) Rétention, indexation, stockage
Chaud : 7-14 jours (enquête rapide).
Chaud : 30-90 jours (tendances, RCA).
Froid : 180-365 + (archives, audit) - compression, classes bon marché, peut-être sans recherche en texte intégral.
Indexation : clés fixes ('service, bou, level, event, trace_id, user. tenant_id'), l'interdiction de l'indice « au total ».
Limites sur la taille de l'événement (par exemple, ≤ 32KB), trim/bas : « superflu dans le stockage est l'ennemi de MTTR ».
11) Audit et invariabilité
Écrivez des événements d'audit avec un thread séparé avec des signatures/hashs, l'heure du serveur, 'who/what/when/why', une référence ticket.
« Qui a inclus le drapeau bonus 100 % dans DE ? » - la réponse doit être dans 1-2 demandes.
json
{
"ts": "2025-11-03T14:00:00.000Z",
"actor": "alice@company",
"action": "feature_flag.update",
"target": "bonus.enable_vip",
"old": {"rollout": 10},
"new": {"rollout": 100},
"reason": "campaign_2311",
"ticket": "OPS-3481",
"trace_id": "cf12ab.."
}
12) Événements commerciaux et modèle de données
Les événements commerciaux ne sont pas un « texte dans les loges », mais un contrat :- `event_type`, `event_id`, `occurred_at`, `actor`, `subject`, `amount`, `currency`, `status`, `idempotency_key`.
- Utilisez Outbox et « at-least-once » avec les consommateurs idempotent.
13) Kubernetes et les loges pipeline
Sidecar/DaemonSet agents avec tampon par disque (en cas de coupures réseau).
Annotations de points de routage ('log. type`, `retention. tier`).
Collectez les logs des contrôleurs K8s séparément (index de cluster).
ini
[FILTER]
Name modify
Match
Remove authorization, password, card_number
14) Anti-modèles
Logs de chaîne « comme il faut », absence de 'trace _ id'.
PII/secrets dans les logs, vides payload entiers.
Des millions de clés uniques → une indexation « éclatée ».
DEBUG en vente 24/7.
Mélanger l'audit, la sécurité et les techniciens en un seul index.
Il n'y a pas de stratégie de rétention ni de test de restauration à partir de l'archive.
15) Chèque de mise en œuvre (0-45 jours)
0-10 jours
Activer W3C Trace Context dans gateway/clients, en-tête.
Convertir les logs d'application en JSON, ajouter 'trace _ id '/' span _ id'.
Interdire les PII/secrets (masquage sur l'agent), approuver la liste des champs.
11-25 jours
Décomposer les flux : tech/biz/audit/security/infra, définir la rétention et l'ACL.
Activer OTel Collector, faire tail-sampling erreurs/requêtes lentes.
Dashboards « Log Rate/Error by route » + Jump-to-trace (Exemplars).
26-45 jours
Alertes selon les modèles d'événements et corrélation avec SLO.
Archive/restauration (DR test) pour les logs froids.
Linter logs schems in CI, contrat pour événements d'affaires.
16) Métriques de maturité
Couverture des requêtes 'trace _ id' ≥ 95 %.
La part des logs JSON ≥ 99 %.
Les incidents trouvés par la via « jump-to-trace » ont été résolus <15 min (p50).
0 cas de PII dans les logs (scanner des fuites).
Retenshn est respecté pour tous les flux (nous prouvons automatiquement l'audit).
17) Applications : Mini-clips
Génération de traceparent W3C (pseudo)
txt traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
BouQL est un groupe de logs et de SLO (exemple)
high_error_logs = rate(log_events_total{service="payments-api",level="ERROR"}[5m])
5xx_rate = sum(rate(http_requests_total{service="payments-api",status=~"5.."}[5m])) / sum(rate(http_requests_total{service="payments-api"}[5m]))
alert if high_error_logs > 10 and 5xx_rate > 0.005
OpenAPI - titres coraliens
yaml components:
parameters:
Traceparent:
name: traceparent in: header required: false schema: { type: string }
18) Conclusion
Un circuit de logage et de traçage fort est un accord + discipline : JSON-logs structurels, un seul 'trace _ id', un traitement PII sécurisé, un routage et un recentrage par flux, ainsi qu'un lien étroit avec SLO, alerting et reculs. Faites la transition de la « décharge de textes » aux contrats d'événements et de pistes, et le diagnostic des incidents prod deviendra rapide, prévisible et vérifiable.