Initial Commit

This commit is contained in:
ivan2282
2025-11-15 20:06:40 +03:00
commit 205d11df0d
233 changed files with 52572 additions and 0 deletions

View File

@@ -0,0 +1,317 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
enum LogLevel { debug, info, warning, error, critical }
class ConnectionLogger {
static final ConnectionLogger _instance = ConnectionLogger._internal();
factory ConnectionLogger() => _instance;
ConnectionLogger._internal();
final List<LogEntry> _logs = [];
final StreamController<LogEntry> _logController =
StreamController<LogEntry>.broadcast();
Stream<LogEntry> get logStream => _logController.stream;
List<LogEntry> get logs => List.unmodifiable(_logs);
static const int maxLogs = 1000;
LogLevel _currentLevel = LogLevel.debug;
void setLogLevel(LogLevel level) {
_currentLevel = level;
}
void log(
String message, {
LogLevel level = LogLevel.info,
String? category,
Map<String, dynamic>? data,
Object? error,
StackTrace? stackTrace,
}) {
if (level.index < _currentLevel.index) return;
final entry = LogEntry(
timestamp: DateTime.now(),
level: level,
message: message,
category: category ?? 'CONNECTION',
data: data,
error: error,
stackTrace: stackTrace,
);
_logs.add(entry);
if (_logs.length > maxLogs) {
_logs.removeRange(0, _logs.length - maxLogs);
}
_logController.add(entry);
if (kDebugMode) {
final emoji = _getEmojiForLevel(level);
final timestamp = entry.timestamp.toIso8601String().substring(11, 23);
final categoryStr = category != null ? '[$category]' : '';
final dataStr = data != null ? ' | Data: ${jsonEncode(data)}' : '';
final errorStr = error != null ? ' | Error: $error' : '';
print('$emoji [$timestamp] $categoryStr $message$dataStr$errorStr');
}
}
void logConnection(
String message, {
Map<String, dynamic>? data,
Object? error,
}) {
log(
message,
level: LogLevel.info,
category: 'CONNECTION',
data: data,
error: error,
);
}
void logError(
String message, {
Map<String, dynamic>? data,
Object? error,
StackTrace? stackTrace,
}) {
log(
message,
level: LogLevel.error,
category: 'ERROR',
data: data,
error: error,
stackTrace: stackTrace,
);
}
void logMessage(
String direction,
dynamic message, {
Map<String, dynamic>? metadata,
}) {
final data = <String, dynamic>{
'direction': direction,
'message': message,
if (metadata != null) ...metadata,
};
log(
'WebSocket $direction',
level: LogLevel.debug,
category: 'WEBSOCKET',
data: data,
);
}
void logReconnect(int attempt, String reason, {Duration? delay}) {
final data = <String, dynamic>{
'attempt': attempt,
'reason': reason,
if (delay != null) 'delay_seconds': delay.inSeconds,
};
log(
'Переподключение: $reason (попытка $attempt)',
level: LogLevel.warning,
category: 'RECONNECT',
data: data,
);
}
void logPerformance(
String operation,
Duration duration, {
Map<String, dynamic>? metadata,
}) {
final data = <String, dynamic>{
'operation': operation,
'duration_ms': duration.inMilliseconds,
if (metadata != null) ...metadata,
};
log(
'Performance: $operation за ${duration.inMilliseconds}ms',
level: LogLevel.debug,
category: 'PERFORMANCE',
data: data,
);
}
void logState(String from, String to, {Map<String, dynamic>? metadata}) {
final data = <String, dynamic>{
'from': from,
'to': to,
if (metadata != null) ...metadata,
};
log(
'Состояние: $from$to',
level: LogLevel.info,
category: 'STATE',
data: data,
);
}
List<LogEntry> getLogsByCategory(String category) {
return _logs.where((log) => log.category == category).toList();
}
List<LogEntry> getLogsByLevel(LogLevel level) {
return _logs.where((log) => log.level == level).toList();
}
Map<String, int> getLogStats() {
final stats = <String, int>{};
for (final log in _logs) {
stats[log.category] = (stats[log.category] ?? 0) + 1;
}
return stats;
}
void clearLogs() {
_logs.clear();
log('Логи очищены', level: LogLevel.info, category: 'LOGGER');
}
String exportLogs() {
final logsJson = _logs.map((log) => log.toJson()).toList();
return jsonEncode(logsJson);
}
void importLogs(String jsonString) {
try {
final List<dynamic> logsList = jsonDecode(jsonString);
_logs.clear();
for (final logJson in logsList) {
_logs.add(LogEntry.fromJson(logJson));
}
log(
'Импортировано ${_logs.length} логов',
level: LogLevel.info,
category: 'LOGGER',
);
} catch (e) {
logError('Ошибка импорта логов', error: e);
}
}
String _getEmojiForLevel(LogLevel level) {
switch (level) {
case LogLevel.debug:
return '🔍';
case LogLevel.info:
return '';
case LogLevel.warning:
return '⚠️';
case LogLevel.error:
return '';
case LogLevel.critical:
return '🚨';
}
}
void dispose() {
_logController.close();
}
}
class LogEntry {
final DateTime timestamp;
final LogLevel level;
final String message;
final String category;
final Map<String, dynamic>? data;
final Object? error;
final StackTrace? stackTrace;
LogEntry({
required this.timestamp,
required this.level,
required this.message,
required this.category,
this.data,
this.error,
this.stackTrace,
});
Map<String, dynamic> toJson() {
return {
'timestamp': timestamp.toIso8601String(),
'level': level.name,
'message': message,
'category': category,
'data': data,
'error': error?.toString(),
'stackTrace': stackTrace?.toString(),
};
}
factory LogEntry.fromJson(Map<String, dynamic> json) {
return LogEntry(
timestamp: DateTime.parse(json['timestamp']),
level: LogLevel.values.firstWhere((l) => l.name == json['level']),
message: json['message'],
category: json['category'],
data: json['data'] != null
? Map<String, dynamic>.from(json['data'])
: null,
error: json['error'],
stackTrace: json['stackTrace'] != null
? StackTrace.fromString(json['stackTrace'])
: null,
);
}
@override
String toString() {
final emoji = _getEmojiForLevel(level);
final timestamp = this.timestamp.toIso8601String().substring(11, 23);
final dataStr = data != null ? ' | Data: ${jsonEncode(data)}' : '';
final errorStr = error != null ? ' | Error: $error' : '';
return '$emoji [$timestamp] [$category] $message$dataStr$errorStr';
}
String _getEmojiForLevel(LogLevel level) {
switch (level) {
case LogLevel.debug:
return '🔍';
case LogLevel.info:
return '';
case LogLevel.warning:
return '⚠️';
case LogLevel.error:
return '';
case LogLevel.critical:
return '🚨';
}
}
}