Skip to content

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 :

typescript
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 :

typescript
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) :

typescript
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 :

typescript
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).