120 lines
4.8 KiB
Markdown
120 lines
4.8 KiB
Markdown
---
|
|
name: production-resilience-observability
|
|
description: >-
|
|
Implement production resilience and observability: nested React Error Boundaries,
|
|
graceful UI degradation, PII-safe telemetry, structured error logging, and retry mechanisms.
|
|
---
|
|
|
|
# Production Resilience & Observability Architecture
|
|
|
|
Ce skill empêche l'écran blanc fatal (*White Screen of Death*). Il impose l'encapsulation modulaire des composants dans des **Error Boundaries** imbriquées, fournit des interfaces de dégradation gracieuse avec réessai sans rechargement de page, et configure la télémétrie conforme au RGPD (anonymisation stricte des données personnelles dans les logs).
|
|
|
|
---
|
|
|
|
## 🎯 Déclencheurs d'Activation
|
|
|
|
Activez ce skill dès que :
|
|
1. Vous intégrez des composants tiers ou dépendants d'un service distant instable (graphiques, flux en direct, météo, intégrations bancaires).
|
|
2. Vous structurez l'architecture racine d'une application ou les gabarits de mise en page (*Layouts*).
|
|
3. Vous mettez en place la capture d'erreurs en production (Sentry, OpenTelemetry, Datadog).
|
|
4. Vous configurez des flux de réessai utilisateur en cas d'échec de rendu.
|
|
5. Vous auditez la protection contre les fuites de données personnelles dans les journaux système (PII Masking).
|
|
|
|
---
|
|
|
|
## 🛡️ 1. Error Boundaries Imbriquées (Isolation des Pannes)
|
|
|
|
Une erreur dans une bannière ou un graphique secondaire ne doit **jamais** casser la barre de navigation ou le tableau de bord principal.
|
|
|
|
```tsx
|
|
'use client';
|
|
|
|
import React from 'react';
|
|
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
|
|
|
|
// Interface de repli modulaire avec bouton de réessai ciblé
|
|
export const ComponentErrorFallback: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {
|
|
return (
|
|
<div
|
|
role="alert"
|
|
className="p-5 rounded-xl bg-rose-500/5 border border-rose-500/20 text-start flex flex-col gap-3"
|
|
>
|
|
<div className="flex items-center gap-2 text-rose-400 font-semibold text-sm">
|
|
<span className="size-2 rounded-full bg-rose-400" />
|
|
Une erreur temporaire est survenue
|
|
</div>
|
|
<p className="text-xs text-white/60">
|
|
Ce widget n'a pas pu être chargé. Les autres services restent pleinement opérationnels.
|
|
</p>
|
|
<button
|
|
type="button"
|
|
onClick={resetErrorBoundary}
|
|
className="self-start px-3 py-1.5 rounded-md text-xs font-medium text-white bg-white/10 hover:bg-white/15
|
|
border border-white/10 transition-all focus-visible:ring-2 focus-visible:ring-rose-400"
|
|
>
|
|
Réessayer le chargement
|
|
</button>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Encapsulation déclarative
|
|
export const SafeWidgetWrapper = ({ children }: { children: React.ReactNode }) => {
|
|
return (
|
|
<ErrorBoundary
|
|
FallbackComponent={ComponentErrorFallback}
|
|
onReset={() => {
|
|
// Nettoyage ou réinitialisation d'état local si besoin
|
|
}}
|
|
onError={(error, info) => {
|
|
// Journalisation sécurisée
|
|
logSafeError(error, info);
|
|
}}
|
|
>
|
|
{children}
|
|
</ErrorBoundary>
|
|
);
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## 🔒 2. Journalisation PII-Safe (Conformité RGPD)
|
|
|
|
Il est illégal et dangereux d'envoyer des mots de passe, tokens JWT ou adresses email privées dans des outils de tracking de bugs comme Sentry ou Datadog :
|
|
|
|
```typescript
|
|
// Filtrage et assainissement des données avant expédition
|
|
export function logSafeError(error: Error, errorInfo?: any) {
|
|
const sanitizedContext = {
|
|
message: error.message,
|
|
stack: error.stack,
|
|
componentStack: errorInfo?.componentStack,
|
|
url: window.location.pathname, // Pas de paramètres de requête sensibles (?token=...)
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
|
|
// Masquage des motifs sensibles (regex token/mot de passe/email)
|
|
const payloadString = JSON.stringify(sanitizedContext)
|
|
.replace(/"(password|token|secret|apiKey)":\s*"[^"]+"/gi, '"$1": "[REDACTED]"')
|
|
.replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, '[EMAIL_REDACTED]');
|
|
|
|
// Expédition sécurisée vers l'outil d'observabilité
|
|
if (process.env.NODE_ENV === 'production') {
|
|
// Sentry.captureException(...) ou fetch('/api/telemetry', { body: payloadString })
|
|
} else {
|
|
console.error('Safe Dev Error Log:', JSON.parse(payloadString));
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Checklist de Conformité Résilience & Observabilité
|
|
|
|
- [ ] Les widgets à risque ou asynchrones sont isolés par leur propre `ErrorBoundary`.
|
|
- [ ] Le composant de repli (*Fallback*) offre un bouton d'action clair pour retenter sans recharger la page entière.
|
|
- [ ] Aucune donnée personnelle (email, mot de passe, token en URL) n'est envoyée aux outils de télémétrie.
|
|
- [ ] Le Layout racine possède une frontière d'erreur globale (`global-error.tsx` dans Next.js).
|
|
- [ ] Les promesses non interceptées (*unhandled rejections*) sont écoutées et journalisées proprement.
|