Logging framework

This commit is contained in:
LittleSheep 2025-02-27 22:58:31 +08:00
parent 1b41c847a6
commit 32bf834108
11 changed files with 173 additions and 15 deletions

View File

@ -727,5 +727,8 @@
"trayMenuMuteNotification": "Do Not Disturb",
"update": "Update",
"forceUpdate": "Force Update",
"forceUpdateDescription": "Force to show the application update popup, even the new version is not available."
"forceUpdateDescription": "Force to show the application update popup, even the new version is not available.",
"debugLogging": "Runtime Logs",
"runtimeLogsOpen": "Open Logs",
"runtimeLogsDescription": "Show the runtime logs to help debugging."
}

View File

@ -725,5 +725,8 @@
"trayMenuMuteNotification": "静音通知",
"update": "更新",
"forceUpdate": "强制更新",
"forceUpdateDescription": "强制更新应用程序,即使有更新的版本可能不可用。"
"forceUpdateDescription": "强制更新应用程序,即使有更新的版本可能不可用。",
"runtimeLogs": "运行时日志",
"runtimeLogsOpen": "打开日志文件",
"runtimeLogsDescription": "显示运行时的日志记录。"
}

View File

@ -725,5 +725,8 @@
"trayMenuMuteNotification": "靜音通知",
"update": "更新",
"forceUpdate": "強制更新",
"forceUpdateDescription": "強制更新應用程序,即使有更新的版本可能不可用。"
"forceUpdateDescription": "強制更新應用程序,即使有更新的版本可能不可用。",
"runtimeLogs": "運行時日誌",
"runtimeLogsOpen": "打開日誌文件",
"runtimeLogsDescription": "顯示運行時的日誌記錄。"
}

View File

@ -725,5 +725,8 @@
"trayMenuMuteNotification": "靜音通知",
"update": "更新",
"forceUpdate": "強制更新",
"forceUpdateDescription": "強制更新應用程序,即使有更新的版本可能不可用。"
"forceUpdateDescription": "強制更新應用程序,即使有更新的版本可能不可用。",
"runtimeLogs": "運行時日誌",
"runtimeLogsOpen": "打開日誌文件",
"runtimeLogsDescription": "顯示運行時的日誌記錄。"
}

3
lib/logger.dart Normal file
View File

@ -0,0 +1,3 @@
import 'package:talker/talker.dart';
final logging = Talker();

View File

@ -20,6 +20,7 @@ import 'package:relative_time/relative_time.dart';
import 'package:responsive_framework/responsive_framework.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:surface/firebase_options.dart';
import 'package:surface/logger.dart';
import 'package:surface/providers/channel.dart';
import 'package:surface/providers/chat_call.dart';
import 'package:surface/providers/config.dart';
@ -235,7 +236,7 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
await inAppReview.requestReview();
prefs.setBool('rating_requested', true);
} else {
log('Unable request app review, unavailable');
logging.error('Unable request app review, unavailable');
}
}
} else {
@ -263,17 +264,18 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
int.tryParse(remoteVersionString.split('+').last) ?? 0;
final localBuildNumber =
int.tryParse(localVersionString.split('+').last) ?? 0;
log("[Update] Local: $localVersionString, Remote: $remoteVersionString");
logging.info(
"[Update] Local: $localVersionString, Remote: $remoteVersionString");
if ((remoteVersion > localVersion ||
remoteBuildNumber > localBuildNumber) &&
mounted) {
final config = context.read<ConfigProvider>();
config.setUpdate(
remoteVersionString, resp.data?['body'] ?? 'No changelog');
log("[Update] Update available: $remoteVersionString");
logging.info("[Update] Update available: $remoteVersionString");
}
} catch (e) {
log('[Error] Unable to check update: $e');
logging.error('[Error] Unable to check update...', e);
if (mounted) context.showErrorDialog('Unable to check update: $e');
}
}
@ -306,7 +308,7 @@ class _AppSplashScreenState extends State<_AppSplashScreen> with TrayListener {
if (!mounted) return;
final sticker = context.read<SnStickerProvider>();
await sticker.listSticker();
log('[Bootstrap] Everything initialized!');
logging.info('[Bootstrap] Everything initialized!');
} catch (err) {
if (!mounted) return;
await context.showErrorDialog(err);

View File

@ -21,6 +21,7 @@ import 'package:surface/screens/chat/room.dart';
import 'package:surface/screens/explore.dart';
import 'package:surface/screens/friend.dart';
import 'package:surface/screens/home.dart';
import 'package:surface/screens/logging.dart';
import 'package:surface/screens/news/news_detail.dart';
import 'package:surface/screens/news/news_list.dart';
import 'package:surface/screens/notification.dart';
@ -249,6 +250,11 @@ final _appRoutes = [
),
],
),
GoRoute(
path: '/debug/logging',
name: 'debugLogging',
builder: (context, state) => const DebugLoggingScreen(),
),
GoRoute(
path: '/album',
name: 'album',

82
lib/screens/logging.dart Normal file
View File

@ -0,0 +1,82 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/logger.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:talker/talker.dart';
final Map<LogLevel, IconData> kLogLevelIcons = {
LogLevel.error: Symbols.error,
LogLevel.critical: Symbols.error,
LogLevel.warning: Symbols.warning,
LogLevel.info: Symbols.info,
LogLevel.debug: Symbols.info_i,
LogLevel.verbose: Symbols.info_i,
};
final Map<LogLevel, Color> kLogLevelColors = {
LogLevel.error: Colors.red,
LogLevel.critical: Colors.red,
LogLevel.warning: Colors.orange,
LogLevel.info: Colors.blue,
LogLevel.debug: Colors.green,
LogLevel.verbose: Colors.green,
};
final Map<LogLevel, bool> kLogLevelFilled = {
LogLevel.error: false,
LogLevel.critical: true,
LogLevel.warning: true,
LogLevel.info: true,
LogLevel.debug: false,
LogLevel.verbose: false,
};
class DebugLoggingScreen extends StatelessWidget {
const DebugLoggingScreen({super.key});
@override
Widget build(BuildContext context) {
return AppScaffold(
appBar: AppBar(
leading: const PageBackButton(),
title: Text('debugLogging').tr(),
),
body: SelectionArea(
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: logging.history.length,
itemBuilder: (context, index) {
final log = logging.history[index];
return ListTile(
leading: Icon(
kLogLevelIcons[log.logLevel ?? LogLevel.debug] ?? Symbols.help,
color: kLogLevelColors[log.logLevel ?? LogLevel.debug],
fill: (kLogLevelFilled[log.logLevel ?? LogLevel.debug] ?? false)
? 1
: 0,
),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
log.message ?? 'unknown'.tr(),
style: GoogleFonts.robotoMono(fontSize: 13),
),
if (log.error != null)
Text(
log.error!.toString(),
style: GoogleFonts.robotoMono(fontSize: 13),
).bold(),
],
),
subtitle: Text(log.time.toString()).fontSize(11),
);
},
),
),
);
}
}

View File

@ -664,6 +664,16 @@ class _SettingsScreenState extends State<SettingsScreen> {
);
},
),
ListTile(
title: Text('runtimeLogsOpen').tr(),
subtitle: Text('runtimeLogsDescription').tr(),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
leading: const Icon(Symbols.receipt_long),
trailing: const Icon(Symbols.chevron_right),
onTap: () async {
GoRouter.of(context).pushNamed('debugLogging');
},
),
ListTile(
title: Text('settingsMiscAbout').tr(),
subtitle: Text('settingsMiscAboutDescription').tr(),

View File

@ -897,18 +897,18 @@ packages:
dependency: "direct dev"
description:
name: freezed
sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c"
sha256: "532008570b7fd20310db8cb9c8ebc5bafd5aa4e52c4358db4e5ddc29f74f4be3"
url: "https://pub.dev"
source: hosted
version: "2.5.8"
version: "3.0.1"
freezed_annotation:
dependency: "direct main"
description:
name: freezed_annotation
sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2
sha256: c87ff004c8aa6af2d531668b46a4ea379f7191dc6dfa066acd53d506da6e044b
url: "https://pub.dev"
source: hosted
version: "2.4.4"
version: "3.0.0"
frontend_server_client:
dependency: transitive
description:
@ -965,6 +965,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
group_button:
dependency: transitive
description:
name: group_button
sha256: "0610fcf28ed122bfb4b410fce161a390f7f2531d55d1d65c5375982001415940"
url: "https://pub.dev"
source: hosted
version: "5.3.4"
highlight:
dependency: transitive
description:
@ -2050,6 +2058,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.1"
talker:
dependency: "direct main"
description:
name: talker
sha256: "5ab7d974ad92042b3e2382441c41ec4c6e5b3fa2b4b024d8ccbfc4bc2244b7bb"
url: "https://pub.dev"
source: hosted
version: "4.6.14"
talker_dio_logger:
dependency: "direct main"
description:
name: talker_dio_logger
sha256: "71780c52951d36e94964ca06158d827dfc67aa2fb75c8b880603cfefa4377b39"
url: "https://pub.dev"
source: hosted
version: "4.6.14"
talker_flutter:
dependency: "direct main"
description:
name: talker_flutter
sha256: "0cc816260b226c0ff930909c9f22984316b652b140f5eabb97ae9813ee0de135"
url: "https://pub.dev"
source: hosted
version: "4.6.14"
talker_logger:
dependency: transitive
description:
name: talker_logger
sha256: "16ff0cfdf011f65b37957c9ff7ef7043dd9f1c8af3ccb4a44ac4a448defb9eb5"
url: "https://pub.dev"
source: hosted
version: "4.6.14"
term_glyph:
dependency: transitive
description:

View File

@ -47,7 +47,7 @@ dependencies:
dio: ^5.7.0
dio_smart_retry: ^7.0.1
very_good_infinite_list: ^0.9.0
freezed_annotation: ^2.4.4
freezed_annotation: ^3.0.0
json_annotation: ^4.9.0
gap: ^3.0.1
markdown: ^7.2.2
@ -130,6 +130,9 @@ dependencies:
local_notifier: ^0.1.6
flutter_markdown_latex: ^0.3.4
flutter_highlight: ^0.7.0
talker_flutter: ^4.6.14
talker_dio_logger: ^4.6.14
talker: ^4.6.14
dev_dependencies:
flutter_test:
@ -142,7 +145,7 @@ dev_dependencies:
# rules and activating additional ones.
flutter_lints: ^5.0.0
build_runner: ^2.4.15
freezed: ^2.5.7
freezed: ^3.0.1
json_serializable: ^6.8.0
icons_launcher: ^3.0.0
flutter_native_splash: ^2.4.2