From 1414083150a25cfa45be939d0cbc14ce51631fad Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Tue, 26 May 2026 11:44:32 +0000 Subject: [PATCH] refa: log (#2216) * refa: log * upgrade deps --- lib/main.dart | 29 +--- lib/pages/setting/pages/logs.dart | 219 ++++++++++++------------------ lib/services/logger.dart | 29 ++-- lib/tcp/live.dart | 2 +- lib/utils/json_file_handler.dart | 39 ++---- pubspec.lock | 58 ++------ pubspec.yaml | 15 +- 7 files changed, 129 insertions(+), 262 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 282fc2144..5ae01fa15 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -13,6 +13,7 @@ import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart'; import 'package:PiliPlus/router/app_pages.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/services/download/download_service.dart'; +import 'package:PiliPlus/services/logger.dart'; import 'package:PiliPlus/services/service_locator.dart'; import 'package:PiliPlus/utils/cache_manager.dart'; import 'package:PiliPlus/utils/calc_window_position.dart'; @@ -181,32 +182,12 @@ void main() async { '${NativePlayer.apiVersion >> 16}.${NativePlayer.apiVersion & 0xFFFF}', }; final fileHandler = await JsonFileHandler.init(); - final Catcher2Options debugConfig = Catcher2Options( - SilentReportMode(), - [ - ?fileHandler, - ConsoleHandler( - enableDeviceParameters: false, - enableApplicationParameters: false, - enableCustomParameters: true, - ), - ], - customParameters: customParameters, - ); - - final Catcher2Options releaseConfig = Catcher2Options( - SilentReportMode(), - [ - ?fileHandler, - ConsoleHandler(enableCustomParameters: true), - ], - customParameters: customParameters, - ); Catcher2( - debugConfig: debugConfig, - releaseConfig: releaseConfig, - rootWidget: const MyApp(), + [?fileHandler, const ConsoleHandler()], + const MyApp(), + logger: logger, + customParameters: customParameters, ); } else { runApp(const MyApp()); diff --git a/lib/pages/setting/pages/logs.dart b/lib/pages/setting/pages/logs.dart index 55aadcfb0..926264e45 100644 --- a/lib/pages/setting/pages/logs.dart +++ b/lib/pages/setting/pages/logs.dart @@ -1,6 +1,7 @@ import 'dart:async' show Timer; import 'dart:convert' show jsonDecode; +import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/scaffold.dart'; @@ -10,8 +11,8 @@ import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:PiliPlus/utils/utils.dart'; -import 'package:catcher_2/model/platform_type.dart'; -import 'package:catcher_2/model/report.dart' as catcher; +import 'package:catcher_2/catcher_2.dart'; +import 'package:catcher_2/utils/log_printer.dart'; import 'package:flutter/foundation.dart' show kDebugMode; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -24,25 +25,25 @@ class LogsPage extends StatefulWidget { } class _LogsPageState extends State { - List logsContent = []; - Report? latestLog; + List<_ExpandedItem> logsContent = []; + _ExpandedItem<_DeviceInfo>? _deviceInfo; late bool enableLog = Pref.enableLog; @override void initState() { + _initDeviceInfo(); getLog(); super.initState(); } - @override - void dispose() { - if (latestLog != null) { - final time = latestLog!.dateTime; - if (DateTime.now().difference(time) >= const Duration(days: 14)) { - LoggerUtils.clearLogs(); - } + void _initDeviceInfo() { + if (Catcher2.instance case final c?) { + _deviceInfo = _ExpandedItem(( + c.deviceParameters, + c.applicationParameters, + c.customParameters, + )); } - super.dispose(); } Future getLog() async { @@ -50,19 +51,18 @@ class _LogsPageState extends State { logsContent = (await logsPath.readAsLines()).reversed.map((i) { try { final log = Report.fromJson(jsonDecode(i)); - latestLog ??= log; - return log; + return _ExpandedItem(log); } catch (e, s) { - return Report( - 'Parse log failed: $e\n\n\n$i', - s, - DateTime.now(), - const {}, - const {}, - const {}, - null, - PlatformType.unknown, - null, + return _ExpandedItem( + Report( + 'Parse log failed: $e\n\n\n$i', + s, + DateTime.now(), + const {}, + const {}, + const {}, + null, + ), ); } }).toList(); @@ -99,7 +99,7 @@ class _LogsPageState extends State { onTap: () => Timer.periodic( const Duration(milliseconds: 3500), (timer) { - Utils.reportError('Manual'); + Utils.reportError('Manual', StackTrace.current); if (timer.tick > 3) { timer.cancel(); if (mounted) getLog(); @@ -121,10 +121,7 @@ class _LogsPageState extends State { child: const Text('复制日志'), ), PopupMenuItem( - onTap: () { - latestLog = null; - clearLogs(); - }, + onTap: clearLogs, child: const Text('清空日志'), ), ], @@ -132,7 +129,7 @@ class _LogsPageState extends State { const SizedBox(width: 6), ], ), - body: logsContent.isNotEmpty + body: logsContent.isNotEmpty || _deviceInfo != null ? Padding( padding: EdgeInsets.only( left: padding.left + 12, @@ -140,11 +137,11 @@ class _LogsPageState extends State { ), child: CustomScrollView( slivers: [ - if (latestLog != null) + if (_deviceInfo != null) SliverToBoxAdapter( child: Padding( padding: const .only(bottom: 12), - child: InfoCard(report: latestLog!), + child: _InfoCard(info: _deviceInfo!), ), ), SliverPadding( @@ -152,7 +149,7 @@ class _LogsPageState extends State { sliver: SliverList.separated( itemCount: logsContent.length, itemBuilder: (context, index) => - ReportCard(report: logsContent[index]), + _ReportCard(report: logsContent[index]), separatorBuilder: (_, _) => const SizedBox(height: 12), ), ), @@ -164,10 +161,16 @@ class _LogsPageState extends State { } } -class InfoCard extends StatelessWidget { - final Report report; +typedef _DeviceInfo = ( + Map, + Map, + Map, +); - const InfoCard({super.key, required this.report}); +class _InfoCard extends StatelessWidget { + final _ExpandedItem<_DeviceInfo> info; + + const _InfoCard({required this.info}); Widget _buildMapSection( Color color, @@ -185,11 +188,7 @@ class InfoCard extends StatelessWidget { const SizedBox(height: 8), Text( title, - style: TextStyle( - fontWeight: FontWeight.bold, - color: color, - fontSize: 15, - ), + style: TextStyle(fontWeight: .bold, color: color, fontSize: 15), ), ...map.entries.map( (entry) => Text.rich( @@ -225,58 +224,47 @@ class InfoCard extends StatelessWidget { const Expanded( child: Text( '相关信息', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 15, - ), + style: TextStyle(fontWeight: .bold, fontSize: 15), maxLines: 1, - overflow: TextOverflow.ellipsis, + overflow: .ellipsis, ), ), iconButton( size: 34, iconSize: 22, + tooltip: info.isExpanded ? '收起' : '展开', icon: Icon( - report.isExpanded ? Icons.expand_less : Icons.expand_more, + info.isExpanded ? Icons.expand_less : Icons.expand_more, ), onPressed: () { - report.isExpanded = !report.isExpanded; + info.isExpanded = !info.isExpanded; (context as Element).markNeedsBuild(); }, ), ], ), - if (report.isExpanded) ...[ - _buildMapSection( - colorScheme.primary, - '设备信息', - report.deviceParameters, - ), - _buildMapSection( - colorScheme.primary, - '应用信息', - report.applicationParameters, - ), - _buildMapSection( - colorScheme.primary, - '编译信息', - report.customParameters, - ), + if (info.isExpanded) ...[ + _buildMapSection(colorScheme.primary, '设备信息', info.item.$1), + _buildMapSection(colorScheme.primary, '应用信息', info.item.$2), + _buildMapSection(colorScheme.primary, '编译信息', info.item.$3), ], ]); } } -class ReportCard extends StatelessWidget { - final Report report; +class _ReportCard extends StatelessWidget { + final _ExpandedItem report; - const ReportCard({super.key, required this.report}); + const _ReportCard({required this.report}); @override Widget build(BuildContext context) { final colorScheme = ColorScheme.of(context); - late final stackTrace = report.stackTrace.toString().trim(); - final dateTime = DateFormatUtils.longFormatDs.format(report.dateTime); + late final stackTrace = PrettyLogPrinter.formatStackString( + report.item.stackTrace?.toString(), + -1, + ); + final dateTime = DateFormatUtils.longFormatDs.format(report.item.dateTime); return _card([ Row( crossAxisAlignment: .start, @@ -287,13 +275,10 @@ class ReportCard extends StatelessWidget { crossAxisAlignment: .start, children: [ Text( - report.error.toString(), - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 15, - ), + report.item.error.toString(), + style: const TextStyle(fontWeight: .bold, fontSize: 15), maxLines: 2, - overflow: TextOverflow.ellipsis, + overflow: .ellipsis, ), Text( dateTime, @@ -318,6 +303,7 @@ class ReportCard extends StatelessWidget { iconButton( size: 34, iconSize: 22, + tooltip: report.isExpanded ? '收起' : '展开', icon: Icon( report.isExpanded ? Icons.expand_less : Icons.expand_more, ), @@ -340,16 +326,14 @@ class ReportCard extends StatelessWidget { ), const SizedBox(height: 8), Container( - padding: const EdgeInsets.all(12), + padding: const .all(12), decoration: BoxDecoration( color: colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(8)), - border: Border.all( - color: colorScheme.outline.withValues(alpha: 0.5), - ), + borderRadius: const .all(.circular(8)), + border: .all(color: colorScheme.outline.withValues(alpha: 0.5)), ), child: SelectableText( - report.error.toString(), + report.item.error.toString(), style: TextStyle( fontFamily: 'Monospace', color: colorScheme.onSurfaceVariant, @@ -357,7 +341,7 @@ class ReportCard extends StatelessWidget { ), ), // stackTrace may be null or String("null") or blank - if (stackTrace.isNotEmpty && stackTrace != 'null') ...[ + if (stackTrace != null && stackTrace.isNotEmpty) ...[ const SizedBox(height: 16), Text( '堆栈跟踪', @@ -369,21 +353,29 @@ class ReportCard extends StatelessWidget { ), const SizedBox(height: 8), Container( - padding: const EdgeInsets.all(12), + padding: const .all(12), decoration: BoxDecoration( color: colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(8)), - border: Border.all( - color: colorScheme.outline.withValues(alpha: 0.5), - ), + borderRadius: const .all(.circular(8)), + border: .all(color: colorScheme.outline.withValues(alpha: 0.5)), ), - child: SelectableText( - stackTrace, - style: TextStyle( - fontFamily: 'Monospace', - fontSize: 13, - color: colorScheme.onSurfaceVariant, + child: SelectableText.rich( + TextSpan( + children: stackTrace + .map( + (i) => TextSpan( + text: '$i\n', + style: i.contains('(package:${Constants.appName}') + ? TextStyle( + color: colorScheme.onSurface, + fontWeight: .w600, + ) + : TextStyle(color: colorScheme.onSurfaceVariant), + ), + ) + .toList(), ), + style: const TextStyle(fontFamily: 'Monospace', fontSize: 13), ), ), ], @@ -404,45 +396,12 @@ Widget _card(List contents) { ); } -class Report extends catcher.Report { - Report( - super.error, - super.stackTrace, - super.dateTime, - super.deviceParameters, - super.applicationParameters, - super.customParameters, - super.errorDetails, - super.platformType, - super.screenshot, - ); - +class _ExpandedItem { bool isExpanded = false; + final T item; - factory Report.fromJson(Map json) => Report( - json['error'], - json['stackTrace'], - DateTime.tryParse(json['dateTime'] ?? '') ?? DateTime(1970), - json['deviceParameters'] ?? const {}, - json['applicationParameters'] ?? const {}, - json['customParameters'] ?? const {}, - null, - PlatformType.values.byName(json['platformType']), - null, - ); - - static String _params2String(Map params) { - return params.entries - .map((entry) => '${entry.key}: ${entry.value}\n') - .join(); - } + _ExpandedItem(this.item); @override - String toString() { - return '------- DEVICE INFO -------\n${_params2String(deviceParameters)}' - '------- APP INFO -------\n${_params2String(applicationParameters)}' - '------- ERROR -------\n$error\n' - '------- STACK TRACE -------\n${stackTrace.toString().trim()}\n' - '------- CUSTOM INFO -------\n${_params2String(customParameters)}'; - } + String toString() => item.toString(); } diff --git a/lib/services/logger.dart b/lib/services/logger.dart index 8cd6e514a..daaac4a53 100644 --- a/lib/services/logger.dart +++ b/lib/services/logger.dart @@ -2,30 +2,19 @@ import 'dart:io' show File; import 'package:PiliPlus/utils/json_file_handler.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; -import 'package:catcher_2/catcher_2.dart'; +import 'package:catcher_2/utils/log_printer.dart'; +import 'package:flutter/foundation.dart'; import 'package:logger/logger.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; -final logger = PiliLogger(); - -class PiliLogger extends Logger { - PiliLogger() : super(); - - @override - void log( - Level level, - dynamic message, { - Object? error, - StackTrace? stackTrace, - DateTime? time, - }) { - if (level == Level.error || level == Level.fatal) { - Catcher2.reportCheckedError(error, stackTrace); - } - super.log(level, message, error: error, stackTrace: stackTrace, time: time); - } -} +final logger = Logger( + filter: ProductionFilter(), + printer: PrettyLogPrinter( + dateTimeFormat: PrettyLogPrinter.toEncodableFallback, + ), + level: kDebugMode ? .trace : .warning, +); abstract final class LoggerUtils { static File? _logFile; diff --git a/lib/tcp/live.dart b/lib/tcp/live.dart index b1c3dd0b4..656092b99 100644 --- a/lib/tcp/live.dart +++ b/lib/tcp/live.dart @@ -49,7 +49,7 @@ class PackageHeaderRes extends PackageHeader { static PackageHeaderRes? fromBytesData(Uint8List data) { if (data.length < 10) { - logger.i('数据不足以解析PackageHeader'); + logger.w('数据不足以解析PackageHeader'); return null; } final byteData = ByteData.sublistView(data); diff --git a/lib/utils/json_file_handler.dart b/lib/utils/json_file_handler.dart index a66016aab..09004c9b6 100644 --- a/lib/utils/json_file_handler.dart +++ b/lib/utils/json_file_handler.dart @@ -1,11 +1,8 @@ import 'dart:convert' show jsonEncode; import 'dart:io' show RandomAccessFile; -import 'package:PiliPlus/services/logger.dart' show LoggerUtils; -import 'package:catcher_2/model/platform_type.dart'; -import 'package:catcher_2/model/report.dart'; -import 'package:catcher_2/model/report_handler.dart'; -import 'package:flutter/material.dart'; +import 'package:PiliPlus/services/logger.dart'; +import 'package:catcher_2/catcher_2.dart'; class JsonFileHandler extends ReportHandler { final bool enableDeviceParameters; @@ -48,7 +45,7 @@ class JsonFileHandler extends ReportHandler { handleWhenRejected: handleWhenRejected, ); } catch (e, s) { - debugPrintStack(stackTrace: s, label: e.toString()); + logger.e('Init log file', error: e, stackTrace: s); return null; } } @@ -62,18 +59,24 @@ class JsonFileHandler extends ReportHandler { } @override - Future handle(Report report, BuildContext? context) async { + Future handle(Report report) async { try { await _processReport(report); return true; } catch (exc, stackTrace) { - _printLog('Exception occurred: $exc stack: $stackTrace'); + logger.e( + 'Write Json Exception occurred', + error: exc, + stackTrace: stackTrace, + ); return false; } } Future _processReport(Report report) { - _printLog('Writing report to file'); + if (printLogs) { + logger.d('Writing report to file'); + } final json = report.toJson( enableDeviceParameters: enableDeviceParameters, enableApplicationParameters: enableApplicationParameters, @@ -82,22 +85,4 @@ class JsonFileHandler extends ReportHandler { ); return add((raf) => raf.writeString('${jsonEncode(json)}\n')); } - - void _printLog(String log) { - if (printLogs) { - logger.info(log); - } - } - - @override - List getSupportedPlatforms() => const [ - PlatformType.android, - PlatformType.iOS, - PlatformType.linux, - PlatformType.macOS, - PlatformType.windows, - ]; - - @override - bool shouldHandleWhenRejected() => handleWhenRejected; } diff --git a/pubspec.lock b/pubspec.lock index 06a3fda07..598dfceea 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,10 +29,10 @@ packages: dependency: "direct main" description: name: app_links - sha256: "3462d9defc61565fde4944858b59bec5be2b9d5b05f20aed190adb3ad08a7abc" + sha256: a408901c5d33e2b5f33064e5db849ce20176e46c5cddb2bf518a5c4c9e7a4e4f url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.1.0" app_links_linux: dependency: transitive description: @@ -240,8 +240,8 @@ packages: description: path: "." ref: dev - resolved-ref: a20878e9fe5375252c9ea22697d4dc4823544b1a - url: "https://github.com/bggRGjQaUbCoE/catcher_2.git" + resolved-ref: "9138d8d2aeefc564efd2f35fde3f54ad1b7e89a7" + url: "https://github.com/My-Responsitories/catcher_2.git" source: git version: "2.1.9" characters: @@ -401,10 +401,10 @@ packages: dependency: "direct main" description: name: dio_http2_adapter - sha256: "79f3d69b155b92a786c8734bd11860390b986210d4e07cbb6a5c8c806a7187b2" + sha256: c56522c50bb3bab7e3ca77c153b0f03ae672a87d8c32e46be8f2868693ec9f0a url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.7.1" dio_web_adapter: dependency: transitive description: @@ -667,14 +667,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_mailer: - dependency: transitive - description: - name: flutter_mailer - sha256: e1c0b4425e3cc789f8dd914fd08b5da660c3ac46c8ebf3e7db183d39775a8fa6 - url: "https://pub.dev" - source: hosted - version: "3.0.2" flutter_native_splash: dependency: "direct dev" description: @@ -1049,14 +1041,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" - mailer: - dependency: transitive - description: - name: mailer - sha256: "7b8691b080809ea1b2fa2f1b0d49c7c089fb328bd23e68aa5818b9cf5f4b420d" - url: "https://pub.dev" - source: hosted - version: "7.1.0" matcher: dependency: transitive description: @@ -1419,14 +1403,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.0" - punycoder: - dependency: transitive - description: - name: punycoder - sha256: aed79c05986a18782caa9bad649a4a786e840e1baaf6a2e1aa3a25d143d28e6e - url: "https://pub.dev" - source: hosted - version: "0.2.2" qr: dependency: transitive description: @@ -1452,7 +1428,7 @@ packages: source: hosted version: "0.6.0" rxdart: - dependency: "direct overridden" + dependency: transitive description: name: rxdart sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" @@ -1463,10 +1439,10 @@ packages: dependency: "direct main" description: name: saver_gallery - sha256: "3f983d4be63aff52523c3e097a9b00ce9ab8444f9a982c878cde9d0359f4681d" + sha256: "5afc7073672f6fd073ddd15118f53f59a2bceee433e586420a3548888cd40820" url: "https://pub.dev" source: hosted - version: "4.1.1" + version: "5.0.2" screen_brightness_android: dependency: "direct overridden" description: @@ -1533,14 +1509,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.0" - sentry: - dependency: transitive - description: - name: sentry - sha256: f04095a25ff02b202a914174c73ec309570aa93d61098cb4a0a9e715b4aaa465 - url: "https://pub.dev" - source: hosted - version: "9.20.0" share_plus: dependency: "direct main" description: @@ -1779,14 +1747,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" - unorm_dart: - dependency: transitive - description: - name: unorm_dart - sha256: "0c69186b03ca6addab0774bcc0f4f17b88d4ce78d9d4d8f0619e30a99ead58e7" - url: "https://pub.dev" - source: hosted - version: "0.3.2" upower: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 901c9384b..1434a3069 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -52,7 +52,7 @@ dependencies: ref: dom catcher_2: git: - url: https://github.com/bggRGjQaUbCoE/catcher_2.git + url: https://github.com/My-Responsitories/catcher_2.git ref: dev characters: ^1.4.1 chat_bottom_container: @@ -66,7 +66,7 @@ dependencies: crypto: ^3.0.6 device_info_plus: ^13.1.0 dio: ^5.9.1 - dio_http2_adapter: ^2.5.3 + dio_http2_adapter: ^2.7.1 dynamic_color: ^1.8.1 easy_debounce: ^2.0.3 encrypt: ^5.0.3 @@ -123,11 +123,7 @@ dependencies: material_new_shapes: ^1.0.0 media_kit: 1.1.11 media_kit_libs_video: 1.0.5 - media_kit_video: - git: - url: https://github.com/bggRGjQaUbCoE/media-kit.git - path: media_kit_video - ref: version_1.2.5 + media_kit_video: 1.2.5 mime: ^2.0.0 native_device_orientation: git: @@ -142,7 +138,7 @@ dependencies: pretty_qr_code: ^3.3.0 protobuf: ^6.0.0 re_highlight: ^0.0.3 - saver_gallery: ^4.1.0 + saver_gallery: ^5.0.2 screen_brightness_platform_interface: ^2.1.0 screen_retriever: ^0.2.0 share_plus: ^13.1.0 @@ -207,9 +203,6 @@ dependency_overrides: url: https://github.com/My-Responsitories/media-kit.git path: media_kit_video ref: version_1.2.5 - mime: ^2.0.0 - path: ^1.9.1 - rxdart: ^0.28.0 screen_brightness_android: git: url: https://github.com/bggRGjQaUbCoE/screen_brightness.git