/// Logger centralisé pour l'application AfterWork. /// /// Ce logger remplace tous les `print()` et `debugPrint()` pour offrir : /// - Niveaux de log structurés (debug, info, warning, error) /// - Filtrage par environnement (dev/prod) /// - Formatage cohérent /// - Support pour stack traces /// /// **Usage:** /// ```dart /// AppLogger.i('Message informatif'); /// AppLogger.e('Erreur', error: e, stackTrace: stackTrace); /// ``` import 'package:flutter/foundation.dart'; import '../constants/env_config.dart'; /// Niveaux de log disponibles. enum LogLevel { /// Messages de débogage (développement uniquement). debug, /// Messages informatifs. info, /// Avertissements. warning, /// Erreurs. error, } /// Logger centralisé pour toute l'application. /// /// Remplace tous les `print()` et `debugPrint()` pour une meilleure /// maintenabilité et performance. class AppLogger { /// Constructeur privé pour empêcher l'instanciation. AppLogger._(); /// Préfixe pour les logs de l'application. static const String _logPrefix = '[AfterWork]'; /// Log un message de niveau DEBUG. /// /// Les messages DEBUG ne sont affichés qu'en mode développement. /// /// [message] Le message à logger /// [tag] Tag optionnel pour catégoriser le log static void d(String message, {String? tag}) { if (EnvConfig.enableDetailedLogs && kDebugMode) { _log(LogLevel.debug, message, tag: tag); } } /// Log un message de niveau INFO. /// /// [message] Le message à logger /// [tag] Tag optionnel pour catégoriser le log static void i(String message, {String? tag}) { if (EnvConfig.enableDetailedLogs || kDebugMode) { _log(LogLevel.info, message, tag: tag); } } /// Log un message de niveau WARNING. /// /// [message] Le message à logger /// [tag] Tag optionnel pour catégoriser le log static void w(String message, {String? tag}) { _log(LogLevel.warning, message, tag: tag); } /// Log un message de niveau ERROR. /// /// [message] Le message à logger /// [error] L'erreur optionnelle /// [stackTrace] La stack trace optionnelle /// [tag] Tag optionnel pour catégoriser le log static void e( String message, { Object? error, StackTrace? stackTrace, String? tag, }) { _log(LogLevel.error, message, tag: tag); if (error != null) { _log(LogLevel.error, 'Error: $error', tag: tag); } if (stackTrace != null) { _log(LogLevel.error, 'StackTrace:\n$stackTrace', tag: tag); } // En production, envoyer à un service de monitoring si configuré if (EnvConfig.isProduction) { // TODO: Intégrer Firebase Crashlytics ou Sentry // _sendToCrashReporting(message, error, stackTrace); } } /// Log une requête HTTP. /// /// [method] La méthode HTTP (GET, POST, etc.) /// [url] L'URL de la requête /// [statusCode] Le code de statut de la réponse /// [duration] La durée de la requête en millisecondes static void http( String method, String url, { int? statusCode, int? duration, }) { if (!EnvConfig.enableDetailedLogs) { return; } final buffer = StringBuffer('HTTP $method $url'); if (statusCode != null) { buffer.write(' → $statusCode'); } if (duration != null) { buffer.write(' (${duration}ms)'); } _log(LogLevel.info, buffer.toString(), tag: 'HTTP'); } /// Méthode privée pour logger avec formatage. static void _log( LogLevel level, String message, { String? tag, }) { final timestamp = DateTime.now().toIso8601String(); final levelStr = _getLevelString(level); final tagStr = tag != null ? '[$tag] ' : ''; final logMessage = '$_logPrefix $timestamp $levelStr $tagStr$message'; if (kDebugMode) { debugPrint(logMessage); } else { // En production, utiliser print uniquement pour les erreurs if (level == LogLevel.error) { print(logMessage); } } } /// Retourne la représentation string du niveau de log. static String _getLevelString(LogLevel level) { switch (level) { case LogLevel.debug: return '[DEBUG]'; case LogLevel.info: return '[INFO] '; case LogLevel.warning: return '[WARN] '; case LogLevel.error: return '[ERROR]'; } } }