Observabilité
Objectifs
- Faciliter le diagnostic rapide des incidents.
- Relier chaque erreur à une requête via
requestId. - Fournir une base de pilotage pour tous les modules métier (auth, booking, finance).
Format de logs
Les logs sont émis en format JSON line via app/mypromo/server/modules/shared/infrastructure/logger.ts.
Champs standard :
| Champ | Description |
|---|---|
timestamp | Date ISO 8601 (ex. 2026-02-09T10:00:00.000Z) |
level | debug / info / warn / error |
scope | Module ou couche émetteur (ex. api-handler, auth-audit) |
message | Description courte de l'événement |
requestId | Identifiant de corrélation (si disponible) |
Exemple :
{
"timestamp": "2026-02-09T10:00:00.000Z",
"level": "error",
"scope": "api-handler",
"message": "request failed",
"requestId": "f7a2f4b6-..."
}
Le niveau minimal de sortie est configurable via la variable d'environnement LOG_LEVEL (valeur par défaut : info). Les niveaux inférieurs au seuil configuré ne produisent aucune sortie.
Corrélation de requêtes
Gérée par app/mypromo/server/middleware/request-id.ts :
- Le middleware lit l'en-tête entrant
x-request-idsi présent et valide (max 128 caractères, pattern^[A-Za-z0-9._:-]+$). - Sinon, il génère un UUID côté serveur.
- L'identifiant est attaché au contexte de l'événement Nitro (
event.context.requestId). - L'en-tête
x-request-idest systématiquement renvoyé dans la réponse.
Tous les appels à log() propagent le requestId du contexte, ce qui permet de regrouper l'ensemble des entrées de log d'une même requête HTTP.
Rate limiting
app/mypromo/server/middleware/rate-limit.ts applique un anti-abus en mémoire sur deux groupes de routes :
| Règle | Routes concernées | Limite |
|---|---|---|
auth-sensitive | /api/auth/sign-in, /api/auth/sign-up, reset mot de passe, vérification email | 10 req/min par IP |
admin-critical | /api/admin/**, /api/auth/assign-role, /api/notifications/email-smoke | 60 req/min par IP |
Les dépassements produisent une réponse 429 Too Many Requests avec un log warn dans le scope api-rate-limit. La réponse JSON contient data.retryAfterSeconds indiquant le délai en secondes avant de réessayer. Les en-têtes x-ratelimit-limit, x-ratelimit-remaining et x-ratelimit-reset sont positionnés uniquement sur les réponses qui ne dépassent pas la limite (requêtes autorisées).
Télémétrie in-process
app/mypromo/server/modules/shared/infrastructure/telemetry.ts maintient des compteurs en mémoire :
apiRequestsTotal— nombre total de requêtes API traitées.apiErrorsTotal— nombre total d'erreurs API.
Ces valeurs sont exposées dans la réponse du health check (champ telemetry). Elles se remettent à zéro au redémarrage du processus.
Health check
Route : GET /api/health
Payload retourné :
{
"service": "pulse-my-promo-api",
"status": "ok",
"environment": "production",
"uptimeSeconds": 3600,
"telemetry": {
"apiRequestsTotal": 1200,
"apiErrorsTotal": 3
}
}
Le handler est défini dans app/mypromo/server/api/health.get.ts. Il n'effectue pas de vérification de connectivité base de données — il sert de signal de vivacité du processus Node.
Audit de sécurité
Les actions sensibles sont persistées en base PostgreSQL via la table SecurityAuditLog (gérée par Prisma). Le repository se trouve dans app/mypromo/server/modules/auth/infrastructure/security-audit.repository.ts.
Événements tracés :
- Auth :
auth.sign_up.*,auth.sign_in.*,auth.magic_link.*,auth.sign_out.success,auth.password_reset.*,auth.email_verification.* - Actions admin : création d'admin, mise à jour utilisateur par admin, création de membership organisation, changement de rôle, KYB, blocage utilisateur
- Invitations organisation : création et acceptation
L'interface admin de consultation est exposée via GET /api/admin/audit/security.
Erreurs non capturées
Le plugin app/mypromo/server/plugins/10-error-logging.ts accroche le hook error de Nitro pour journaliser toute erreur serveur non gérée par un handler, avec le requestId associé lorsqu'il est disponible.
Arrêt propre
app/mypromo/server/plugins/99-prisma-close.ts accroche le hook close de Nitro pour déconnecter explicitement le client Prisma à l'arrêt du processus, évitant les connexions PostgreSQL pendantes.
Seuils d'alerte
Les seuils suivants sont des seuils de référence proposés, à configurer dans l'outil de monitoring retenu. Ils ne sont pas câblés à un système d'alerte actif à ce stade :
| Condition | Seuil proposé |
|---|---|
| Taux d'erreurs 5xx | > 2 % sur 5 min |
| Health check indisponible | > 2 min |
| Build CI en échec sur branche principale | immédiat |
Bonnes pratiques
- Ne jamais logger de secrets : clés API, mots de passe, tokens.
- Limiter la taille des payloads loggés.
- Préférer des codes d'erreur stables (
error.code) aux messages libres. - Utiliser le champ
scopepour identifier clairement la couche émettrice.