Clean project: remove test files, debug logs, and add documentation
This commit is contained in:
301
unionflow-mobile-apps/lib/core/utils/logger.dart
Normal file
301
unionflow-mobile-apps/lib/core/utils/logger.dart
Normal file
@@ -0,0 +1,301 @@
|
||||
/// Logger centralisé pour l'application
|
||||
library logger;
|
||||
|
||||
import 'package:flutter/foundation.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 (AppConstants.enableLogging && kDebugMode) {
|
||||
_log(LogLevel.debug, message, tag: tag, color: _blue);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau INFO (vert)
|
||||
static void info(String message, {String? tag}) {
|
||||
if (AppConstants.enableLogging && kDebugMode) {
|
||||
_log(LogLevel.info, message, tag: tag, color: _green);
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau WARNING (jaune)
|
||||
static void warning(String message, {String? tag}) {
|
||||
if (AppConstants.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 (AppConstants.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);
|
||||
}
|
||||
|
||||
// TODO: Envoyer à un service de monitoring (Sentry, Firebase Crashlytics)
|
||||
if (AppConstants.enableCrashReporting) {
|
||||
_sendToMonitoring(message, error, stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Log de niveau FATAL (magenta)
|
||||
static void fatal(
|
||||
String message, {
|
||||
String? tag,
|
||||
dynamic error,
|
||||
StackTrace? stackTrace,
|
||||
}) {
|
||||
if (AppConstants.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);
|
||||
}
|
||||
|
||||
// TODO: Envoyer à un service de monitoring (Sentry, Firebase Crashlytics)
|
||||
if (AppConstants.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 (AppConstants.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 (AppConstants.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 (AppConstants.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 (AppConstants.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 (AppConstants.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 (AppConstants.enableLogging && kDebugMode) {
|
||||
final message = data != null
|
||||
? 'User Action: $action | Data: $data'
|
||||
: 'User Action: $action';
|
||||
_log(LogLevel.info, message, color: _green);
|
||||
}
|
||||
|
||||
// TODO: Envoyer à un service d'analytics
|
||||
if (AppConstants.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');
|
||||
}
|
||||
}
|
||||
|
||||
/// Envoyer les erreurs à un service de monitoring
|
||||
static void _sendToMonitoring(
|
||||
String message,
|
||||
dynamic error,
|
||||
StackTrace? stackTrace, {
|
||||
bool isFatal = false,
|
||||
}) {
|
||||
// TODO: Implémenter l'envoi à Sentry, Firebase Crashlytics, etc.
|
||||
// Exemple avec Sentry:
|
||||
// Sentry.captureException(
|
||||
// error,
|
||||
// stackTrace: stackTrace,
|
||||
// hint: Hint.withMap({'message': message}),
|
||||
// );
|
||||
}
|
||||
|
||||
/// Envoyer les événements à un service d'analytics
|
||||
static void _sendToAnalytics(String action, Map<String, dynamic>? data) {
|
||||
// TODO: Implémenter l'envoi à Firebase Analytics, Mixpanel, etc.
|
||||
// Exemple avec Firebase Analytics:
|
||||
// FirebaseAnalytics.instance.logEvent(
|
||||
// name: action,
|
||||
// parameters: data,
|
||||
// );
|
||||
}
|
||||
|
||||
/// Divider pour séparer visuellement les logs
|
||||
static void divider({String? title}) {
|
||||
if (AppConstants.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