Logging et observabilite
Le bot utilise trois systemes de logging complementaires.
Pino (logs console)
Logger principal base sur Pino. Configuration dans src/config/logger.ts.
Child loggers
Chaque module cree un child logger avec le nom du module :
import { logger } from '../../../config/logger.js';
const log = logger.child({ module: 'my-module' });
log.info({ userId: '123' }, 'Action effectuee');
log.error({ err }, 'Erreur critique');Niveaux de log
Les niveaux standard de Pino : debug, info, warn, error, fatal.
Le niveau est configure via LOG_LEVEL dans le .env (defaut info).
Mode developpement
En NODE_ENV=development, Pino utilise pino-pretty pour un affichage lisible avec couleurs et timestamps formates (HH:MM:ss).
SystemLog (base de donnees)
Table SystemLog pour le stockage persistant. Utilisee via le service systemLogService :
import { systemLogService } from '../../../shared/services/system-log.service.js';
await systemLogService.info('my-module', 'Action effectuee', { detail: 'value' });
await systemLogService.warn('my-module', 'Situation anormale', { reason: '...' });
await systemLogService.error('my-module', 'Erreur', { error: msg });Les logs de plus de 30 jours sont purges automatiquement par le cron cache-purge.
Les 5 derniers logs d'erreur sont inclus dans les rapports de bug (/bug).
AuditLog (base de donnees)
Table AuditLog pour le suivi des actions utilisateur (setup, moderation, admin XP) :
import { auditLogService } from '../../../shared/services/audit-log.service.js';
await auditLogService.log({
guildId: env.DISCORD_GUILD_ID,
userId: interaction.user.id, // discordId, resolu en profileId
action: 'MY_ACTION',
details: { param1: 'value1' },
});Le userId est un Discord ID. Le service le resout automatiquement en UserProfile.id via une requete.
notifyAdminChannel (Discord)
Envoie une notification dans le salon admin Discord :
import { notifyAdminChannel } from '../../../infrastructure/discord/notifier.js';
await notifyAdminChannel('Message important', 'info');
await notifyAdminChannel('Attention', 'warn');
await notifyAdminChannel('Erreur critique', 'error');Trois niveaux avec icônes : 🟢 info, 🟡 warn, 🔴 error.
Format du message : <icone> <timestamp ISO> <message>
Il existe aussi notifyModerationChannel(guildId, message) qui envoie dans le salon de moderation si configure, sinon dans le salon admin.
Regles de gestion d'erreur par couche
Commandes
Le dispatcher central dans bootstrap.ts attrape toutes les erreurs des commandes :
- Logue l'erreur avec Pino.
- Repond a l'utilisateur avec un message generique.
- Notifie le salon admin.
Les commandes n'ont pas besoin de try/catch sauf pour des cas specifiques (defer, actions partielles).
Handlers
Chaque handler doit wrapper sa logique dans un try/catch :
- Logue l'erreur.
- Notifie le salon admin avec
.catch(() => null). - Ne pas propager l'erreur (risque de crash du bot).
Crons
La fonction registerCron gere automatiquement les erreurs :
- Logue l'erreur.
- Notifie le salon admin.
- Le cron continue de s'executer aux prochaines occurrences.
Global
Deux handlers de dernier recours :
uncaughtException: log fatal + notification +process.exit(1).unhandledRejection: log error + notification (pas de crash).
