Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts). Signed-off-by: lions dev Team
This commit is contained in:
325
lib/core/utils/logger.dart
Normal file
325
lib/core/utils/logger.dart
Normal file
@@ -0,0 +1,325 @@
|
||||
/// Logger centralisé pour l'application
|
||||
library logger;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../config/environment.dart';
|
||||
import '../constants/app_constants.dart';
|
||||
|
||||
/// Niveaux de log
|
||||
enum LogLevel {
|
||||
debug,
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
fatal,
|
||||
}
|
||||
|
||||
/// Logger centralisé pour toute l'application
|
||||
class AppLogger {
|
||||
// Empêcher l'instanciation
|
||||
AppLogger._();
|
||||
|
||||
/// Couleurs ANSI pour les logs en console
|
||||
static const String _reset = '\x1B[0m';
|
||||
static const String _red = '\x1B[31m';
|
||||
static const String _green = '\x1B[32m';
|
||||
static const String _yellow = '\x1B[33m';
|
||||
static const String _blue = '\x1B[34m';
|
||||
static const String _magenta = '\x1B[35m';
|
||||
static const String _cyan = '\x1B[36m';
|
||||
static const String _white = '\x1B[37m';
|
||||
|
||||
/// Log de niveau DEBUG (bleu)
|
||||
static void debug(String message, {String? tag}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
_log(LogLevel.debug, message, tag: tag, color: _blue);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau INFO (vert)
|
||||
static void info(String message, {String? tag}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
_log(LogLevel.info, message, tag: tag, color: _green);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau WARNING (jaune)
|
||||
static void warning(String message, {String? tag}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
_log(LogLevel.warning, message, tag: tag, color: _yellow);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau ERROR (rouge)
|
||||
static void error(
|
||||
String message, {
|
||||
String? tag,
|
||||
dynamic error,
|
||||
StackTrace? stackTrace,
|
||||
}) {
|
||||
if (AppConfig.enableLogging) {
|
||||
_log(LogLevel.error, message, tag: tag, color: _red);
|
||||
|
||||
if (error != null) {
|
||||
_log(LogLevel.error, 'Error: $error', tag: tag, color: _red);
|
||||
}
|
||||
|
||||
if (stackTrace != null) {
|
||||
_log(LogLevel.error, 'StackTrace:\n$stackTrace', tag: tag, color: _red);
|
||||
}
|
||||
|
||||
// Envoi au service de monitoring si configuré
|
||||
if (AppConfig.enableCrashReporting) {
|
||||
_sendToMonitoring(message, error, stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau FATAL (magenta)
|
||||
static void fatal(
|
||||
String message, {
|
||||
String? tag,
|
||||
dynamic error,
|
||||
StackTrace? stackTrace,
|
||||
}) {
|
||||
if (AppConfig.enableLogging) {
|
||||
_log(LogLevel.fatal, message, tag: tag, color: _magenta);
|
||||
|
||||
if (error != null) {
|
||||
_log(LogLevel.fatal, 'Error: $error', tag: tag, color: _magenta);
|
||||
}
|
||||
|
||||
if (stackTrace != null) {
|
||||
_log(LogLevel.fatal, 'StackTrace:\n$stackTrace', tag: tag, color: _magenta);
|
||||
}
|
||||
|
||||
// Envoi au service de monitoring si configuré
|
||||
if (AppConfig.enableCrashReporting) {
|
||||
_sendToMonitoring(message, error, stackTrace, isFatal: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Log d'une requête HTTP
|
||||
static void httpRequest({
|
||||
required String method,
|
||||
required String url,
|
||||
Map<String, dynamic>? headers,
|
||||
dynamic body,
|
||||
}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('┌─────────────────────────────────────────────────');
|
||||
buffer.writeln('│ HTTP REQUEST');
|
||||
buffer.writeln('├─────────────────────────────────────────────────');
|
||||
buffer.writeln('│ Method: $method');
|
||||
buffer.writeln('│ URL: $url');
|
||||
|
||||
if (headers != null && headers.isNotEmpty) {
|
||||
buffer.writeln('│ Headers:');
|
||||
headers.forEach((key, value) {
|
||||
buffer.writeln('│ $key: $value');
|
||||
});
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
buffer.writeln('│ Body: $body');
|
||||
}
|
||||
|
||||
buffer.writeln('└─────────────────────────────────────────────────');
|
||||
|
||||
_log(LogLevel.debug, buffer.toString(), color: _cyan);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log d'une réponse HTTP
|
||||
static void httpResponse({
|
||||
required int statusCode,
|
||||
required String url,
|
||||
Map<String, dynamic>? headers,
|
||||
dynamic body,
|
||||
Duration? duration,
|
||||
}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('┌─────────────────────────────────────────────────');
|
||||
buffer.writeln('│ HTTP RESPONSE');
|
||||
buffer.writeln('├─────────────────────────────────────────────────');
|
||||
buffer.writeln('│ Status: $statusCode');
|
||||
buffer.writeln('│ URL: $url');
|
||||
|
||||
if (duration != null) {
|
||||
buffer.writeln('│ Duration: ${duration.inMilliseconds}ms');
|
||||
}
|
||||
|
||||
if (headers != null && headers.isNotEmpty) {
|
||||
buffer.writeln('│ Headers:');
|
||||
headers.forEach((key, value) {
|
||||
buffer.writeln('│ $key: $value');
|
||||
});
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
buffer.writeln('│ Body: $body');
|
||||
}
|
||||
|
||||
buffer.writeln('└─────────────────────────────────────────────────');
|
||||
|
||||
final color = statusCode >= 200 && statusCode < 300 ? _green : _red;
|
||||
_log(LogLevel.debug, buffer.toString(), color: color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log d'un événement BLoC
|
||||
static void blocEvent(String blocName, String eventName, {dynamic data}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
final message = data != null
|
||||
? '[$blocName] Event: $eventName | Data: $data'
|
||||
: '[$blocName] Event: $eventName';
|
||||
_log(LogLevel.debug, message, color: _cyan);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log d'un changement d'état BLoC
|
||||
static void blocState(String blocName, String stateName, {dynamic data}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
final message = data != null
|
||||
? '[$blocName] State: $stateName | Data: $data'
|
||||
: '[$blocName] State: $stateName';
|
||||
_log(LogLevel.debug, message, color: _magenta);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log d'une navigation
|
||||
static void navigation(String from, String to) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
_log(LogLevel.debug, 'Navigation: $from → $to', color: _yellow);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log d'une action utilisateur
|
||||
static void userAction(String action, {Map<String, dynamic>? data}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
final message = data != null
|
||||
? 'User Action: $action | Data: $data'
|
||||
: 'User Action: $action';
|
||||
_log(LogLevel.info, message, color: _green);
|
||||
}
|
||||
|
||||
// Envoi au service d'analytics si configuré
|
||||
if (AppConfig.enableAnalytics) {
|
||||
_sendToAnalytics(action, data);
|
||||
}
|
||||
}
|
||||
|
||||
/// Méthode privée pour logger avec formatage
|
||||
static void _log(
|
||||
LogLevel level,
|
||||
String message, {
|
||||
String? tag,
|
||||
String color = _white,
|
||||
}) {
|
||||
final timestamp = DateTime.now().toIso8601String();
|
||||
final levelStr = level.name.toUpperCase().padRight(7);
|
||||
final tagStr = tag != null ? '[$tag] ' : '';
|
||||
|
||||
if (kDebugMode) {
|
||||
// En mode debug, utiliser les couleurs
|
||||
debugPrint('$color$timestamp | $levelStr | $tagStr$message$_reset');
|
||||
} else {
|
||||
// En mode release, pas de couleurs
|
||||
debugPrint('$timestamp | $levelStr | $tagStr$message');
|
||||
}
|
||||
}
|
||||
|
||||
/// Callback optionnel pour envoyer les erreurs au monitoring (Sentry / Firebase Crashlytics).
|
||||
/// À enregistrer au démarrage de l'app quand le SDK est intégré.
|
||||
static void Function(String message, dynamic error, StackTrace? stackTrace, {bool isFatal})? onMonitoringReport;
|
||||
|
||||
/// Callback optionnel pour envoyer les événements analytics (Firebase Analytics / Mixpanel).
|
||||
/// À enregistrer au démarrage de l'app quand le SDK est intégré.
|
||||
static void Function(String action, Map<String, dynamic>? data)? onAnalyticsEvent;
|
||||
|
||||
/// Envoyer les erreurs à un service de monitoring
|
||||
static void _sendToMonitoring(
|
||||
String message,
|
||||
dynamic error,
|
||||
StackTrace? stackTrace, {
|
||||
bool isFatal = false,
|
||||
}) {
|
||||
if (onMonitoringReport != null) {
|
||||
try {
|
||||
onMonitoringReport!(message, error, stackTrace, isFatal: isFatal);
|
||||
} catch (e, st) {
|
||||
if (kDebugMode) {
|
||||
debugPrint('AppLogger: échec envoi monitoring: $e');
|
||||
debugPrint('$st');
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (kDebugMode && (error != null || stackTrace != null)) {
|
||||
debugPrint('AppLogger: monitoring non configuré (enregistrer onMonitoringReport pour Sentry/Crashlytics)');
|
||||
}
|
||||
}
|
||||
|
||||
/// Envoyer les événements à un service d'analytics
|
||||
static void _sendToAnalytics(String action, Map<String, dynamic>? data) {
|
||||
if (onAnalyticsEvent != null) {
|
||||
try {
|
||||
onAnalyticsEvent!(action, data);
|
||||
} catch (e, st) {
|
||||
if (kDebugMode) {
|
||||
debugPrint('AppLogger: échec envoi analytics: $e');
|
||||
debugPrint('$st');
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (kDebugMode) {
|
||||
debugPrint('AppLogger: analytics non configuré (enregistrer onAnalyticsEvent pour Firebase/Mixpanel)');
|
||||
}
|
||||
}
|
||||
|
||||
/// Divider pour séparer visuellement les logs
|
||||
static void divider({String? title}) {
|
||||
if (AppConfig.enableLogging && kDebugMode) {
|
||||
if (title != null) {
|
||||
debugPrint('$_cyan═══════════════════════════════════════════════════$_reset');
|
||||
debugPrint('$_cyan $title$_reset');
|
||||
debugPrint('$_cyan═══════════════════════════════════════════════════$_reset');
|
||||
} else {
|
||||
debugPrint('$_cyan═══════════════════════════════════════════════════$_reset');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension pour faciliter le logging depuis n'importe où
|
||||
extension LoggerExtension on Object {
|
||||
/// Log debug
|
||||
void logDebug(String message) {
|
||||
AppLogger.debug(message, tag: runtimeType.toString());
|
||||
}
|
||||
|
||||
/// Log info
|
||||
void logInfo(String message) {
|
||||
AppLogger.info(message, tag: runtimeType.toString());
|
||||
}
|
||||
|
||||
/// Log warning
|
||||
void logWarning(String message) {
|
||||
AppLogger.warning(message, tag: runtimeType.toString());
|
||||
}
|
||||
|
||||
/// Log error
|
||||
void logError(String message, {dynamic error, StackTrace? stackTrace}) {
|
||||
AppLogger.error(
|
||||
message,
|
||||
tag: runtimeType.toString(),
|
||||
error: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user