update
Some checks failed
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled

(cherry picked from commit 52f368c3417efe0e88052bb811c8fc8d8fb7e8b9)
This commit is contained in:
Rust 2025-11-02 17:10:52 +08:00 committed by speakeloudest
parent f1e8e7f530
commit b8d0417d0f

View File

@ -0,0 +1,308 @@
import 'dart:io';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
import 'package:intl/intl.dart';
import '../common/app_config.dart';
///
/// 便
///
/// 使
/// 1. AppConfig.enableInitLogCollection
/// 2. {}/init_logs/init_log_yyyyMMdd_HHmmss.txt
/// 3. 5
class KRInitLogCollector {
static final KRInitLogCollector _instance = KRInitLogCollector._internal();
factory KRInitLogCollector() => _instance;
KRInitLogCollector._internal();
///
File? _logFile;
/// 🔧 使 RandomAccessFile
RandomAccessFile? _logFileHandle;
///
final List<String> _logBuffer = [];
///
bool _isInitialized = false;
///
DateTime? _initStartTime;
///
String? _logFilePath;
/// 🔧
bool get _isEnabled => AppConfig.enableInitLogCollection;
///
Future<void> initialize() async {
// 🔧
if (!_isEnabled) {
if (kDebugMode) {
print('📝 初始化日志收集已关闭AppConfig.enableInitLogCollection = false');
}
return;
}
if (_isInitialized) return;
try {
_initStartTime = DateTime.now();
//
final directory = await getApplicationDocumentsDirectory();
final logDir = Directory('${directory.path}/init_logs');
//
if (!await logDir.exists()) {
await logDir.create(recursive: true);
}
// 使
final timestamp = DateFormat('yyyyMMdd_HHmmss').format(_initStartTime!);
_logFile = File('${logDir.path}/init_log_$timestamp.txt');
_logFilePath = _logFile!.path;
// 🔧 使 RandomAccessFile
_logFileHandle = await _logFile!.open(mode: FileMode.write);
//
_writeHeader();
//
if (_logBuffer.isNotEmpty) {
for (var log in _logBuffer) {
_writeToFile(log);
}
_logBuffer.clear();
}
_isInitialized = true;
// 便
if (kDebugMode) {
print('📝 初始化日志文件已创建: $_logFilePath');
}
// 5
await _cleanOldLogs(logDir);
} catch (e) {
if (kDebugMode) {
print('❌ 初始化日志收集器失败: $e');
}
}
}
///
void _writeHeader() {
final header = '''
: ${DateFormat('yyyy-MM-dd HH:mm:ss').format(_initStartTime!)}
: ${Platform.operatingSystem} ${Platform.operatingSystemVersion}
Flutter版本: ${Platform.version}
''';
_writeToFile(header);
}
///
void log(String message, {String tag = 'INIT'}) {
// 🔧
if (!_isEnabled) return;
final timestamp = DateTime.now();
final elapsed = _initStartTime != null
? timestamp.difference(_initStartTime!).inMilliseconds
: 0;
final logLine = '[${DateFormat('HH:mm:ss.SSS').format(timestamp)}] '
'[+${elapsed}ms] '
'[$tag] '
'$message';
// DEBUG模式
if (kDebugMode) {
print(logLine);
}
// 🔧 RandomAccessFile
if (_isInitialized && _logFileHandle != null) {
_writeToFile('$logLine\n');
} else {
//
_logBuffer.add('$logLine\n');
}
}
/// 线
void logSeparator() {
log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: '');
}
///
void logError(String message, {String tag = 'ERROR', Object? error, StackTrace? stackTrace}) {
log('$message', tag: tag);
if (error != null) {
log(' 错误详情: $error', tag: tag);
}
if (stackTrace != null) {
log(' 堆栈跟踪: $stackTrace', tag: tag);
}
}
///
void logWarning(String message, {String tag = 'WARN'}) {
log('⚠️ $message', tag: tag);
}
///
void logSuccess(String message, {String tag = 'SUCCESS'}) {
log('$message', tag: tag);
}
///
void logPhaseStart(String phase) {
logSeparator();
log('🎬 开始阶段: $phase', tag: 'PHASE');
logSeparator();
}
///
void logPhaseEnd(String phase, {bool success = true}) {
final icon = success ? '' : '';
log('$icon 完成阶段: $phase', tag: 'PHASE');
logSeparator();
}
/// 🔧 使 RandomAccessFile
void _writeToFile(String content) {
try {
if (_logFileHandle != null) {
// 使 writeStringSync
_logFileHandle!.writeStringSync(content);
//
_logFileHandle!.flushSync();
}
} catch (e, stackTrace) {
if (kDebugMode) {
print('❌ 写入日志文件失败: $e');
print('📚 堆栈跟踪: $stackTrace');
}
//
if (kDebugMode) {
print('[日志备份] $content');
}
}
}
/// N个
Future<void> _cleanOldLogs(Directory logDir, {int keepCount = 5}) async {
try {
final files = logDir.listSync()
.whereType<File>()
.where((f) => f.path.contains('init_log_'))
.toList();
if (files.length <= keepCount) return;
//
files.sort((a, b) => b.lastModifiedSync().compareTo(a.lastModifiedSync()));
//
for (var i = keepCount; i < files.length; i++) {
await files[i].delete();
if (kDebugMode) {
print('🧹 已删除旧日志文件: ${files[i].path}');
}
}
} catch (e) {
if (kDebugMode) {
print('❌ 清理旧日志文件失败: $e');
}
}
}
///
Future<void> finalize() async {
if (!_isInitialized || _logFileHandle == null) return;
try {
final endTime = DateTime.now();
final totalDuration = endTime.difference(_initStartTime!);
final footer = '''
: ${DateFormat('yyyy-MM-dd HH:mm:ss').format(endTime)}
: ${totalDuration.inMilliseconds}ms (${totalDuration.inSeconds})
''';
_writeToFile(footer);
// 🔧 使
_logFileHandle!.flushSync();
await _logFileHandle!.close();
_logFileHandle = null;
if (kDebugMode) {
print('📝 初始化日志已完成: $_logFilePath');
print('📊 总耗时: ${totalDuration.inMilliseconds}ms');
}
} catch (e, stackTrace) {
if (kDebugMode) {
print('❌ 完成日志记录失败: $e');
print('📚 堆栈跟踪: $stackTrace');
}
}
}
///
String? getLogFilePath() => _logFilePath;
///
Future<List<File>> getAllLogFiles() async {
try {
final directory = await getApplicationDocumentsDirectory();
final logDir = Directory('${directory.path}/init_logs');
if (!await logDir.exists()) return [];
return logDir.listSync()
.whereType<File>()
.where((f) => f.path.contains('init_log_'))
.toList()
..sort((a, b) => b.lastModifiedSync().compareTo(a.lastModifiedSync()));
} catch (e) {
if (kDebugMode) {
print('❌ 获取日志文件列表失败: $e');
}
return [];
}
}
///
Future<File?> getLatestLogFile() async {
final files = await getAllLogFiles();
return files.isNotEmpty ? files.first : null;
}
///
Future<String> readLogFile(File file) async {
try {
return await file.readAsString();
} catch (e) {
return '读取日志文件失败: $e';
}
}
}