302 lines
9.6 KiB
Dart
302 lines
9.6 KiB
Dart
/// 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,
|
|
);
|
|
}
|
|
}
|
|
|