Backup before removing hiddify references

This commit is contained in:
Hiddify User
2026-01-15 12:28:40 +03:00
parent f54603d129
commit 36d9e31236
231 changed files with 6648 additions and 1832 deletions

View File

@@ -1,3 +1,4 @@
import 'dart:io';
import 'package:fpdart/fpdart.dart';
import 'package:hiddify/core/utils/exception_handler.dart';
import 'package:hiddify/features/log/data/log_parser.dart';
@@ -13,9 +14,7 @@ abstract interface class LogRepository {
TaskEither<LogFailure, Unit> clearLogs();
}
class LogRepositoryImpl
with ExceptionHandler, InfraLogger
implements LogRepository {
class LogRepositoryImpl with ExceptionHandler, InfraLogger implements LogRepository {
LogRepositoryImpl({
required this.singbox,
required this.logPathResolver,
@@ -24,6 +23,10 @@ class LogRepositoryImpl
final SingboxService singbox;
final LogPathResolver logPathResolver;
// Ограничения на размер файлов логов
static const int _maxLogFileSize = 5 * 1024 * 1024; // 5 МБ
static const int _maxBackupFiles = 2; // Храним только 2 backup файла
@override
TaskEither<LogFailure, Unit> init() {
return exceptionHandler(
@@ -31,28 +34,84 @@ class LogRepositoryImpl
if (!await logPathResolver.directory.exists()) {
await logPathResolver.directory.create(recursive: true);
}
if (await logPathResolver.coreFile().exists()) {
await logPathResolver.coreFile().writeAsString("");
} else {
await logPathResolver.coreFile().create(recursive: true);
}
if (await logPathResolver.appFile().exists()) {
await logPathResolver.appFile().writeAsString("");
} else {
await logPathResolver.appFile().create(recursive: true);
}
// Инициализация core логов с ротацией
await _initLogFileWithRotation(logPathResolver.coreFile());
// Инициализация app логов с ротацией
await _initLogFileWithRotation(logPathResolver.appFile());
return right(unit);
},
LogUnexpectedFailure.new,
);
}
/// Инициализация файла логов с автоматической ротацией
Future<void> _initLogFileWithRotation(File logFile) async {
try {
if (await logFile.exists()) {
final fileSize = await logFile.length();
// Если файл превышает лимит - делаем ротацию
if (fileSize > _maxLogFileSize) {
loggy.info('Log file too large: ${fileSize / 1024 / 1024}MB, rotating...');
await _rotateLogFile(logFile);
} else {
// Просто очищаем если размер нормальный
await logFile.writeAsString("");
}
} else {
await logFile.create(recursive: true);
}
} catch (e, st) {
loggy.warning('Error initializing log file: $e', e, st);
// В случае ошибки просто создаём новый файл
await logFile.create(recursive: true);
}
}
/// Ротация файла логов (создаём backup и очищаем текущий)
Future<void> _rotateLogFile(File logFile) async {
try {
final basePath = logFile.path;
// Удаляем самый старый backup если есть
for (int i = _maxBackupFiles; i > 0; i--) {
final oldBackup = File('$basePath.$i');
if (i == _maxBackupFiles && await oldBackup.exists()) {
await oldBackup.delete();
loggy.debug('Deleted old backup: $basePath.$i');
}
// Переименовываем backups (example.log.1 → example.log.2)
if (i > 1) {
final prevBackup = File('$basePath.${i - 1}');
if (await prevBackup.exists()) {
await prevBackup.rename('$basePath.$i');
}
}
}
// Текущий файл → backup.1
if (await logFile.exists()) {
await logFile.rename('$basePath.1');
loggy.debug('Rotated log file to: $basePath.1');
}
// Создаём новый пустой файл
await logFile.create();
loggy.info('Log file rotation completed successfully');
} catch (e, st) {
loggy.warning('Error rotating log file: $e', e, st);
// В случае ошибки просто перезаписываем файл
await logFile.writeAsString("");
}
}
@override
Stream<Either<LogFailure, List<LogEntity>>> watchLogs() {
return singbox
.watchLogs(logPathResolver.coreFile().path)
.map((event) => event.map(LogParser.parseSingbox).toList())
.handleExceptions(
return singbox.watchLogs(logPathResolver.coreFile().path).map((event) => event.map(LogParser.parseSingbox).toList()).handleExceptions(
(error, stackTrace) {
loggy.warning("error watching logs", error, stackTrace);
return LogFailure.unexpected(error, stackTrace);