From 0940a7881134065b2ead8634481a829c9bca577b Mon Sep 17 00:00:00 2001 From: Yesterday17 Date: Sat, 24 Aug 2024 13:01:25 +0800 Subject: [PATCH] refactor: move some simple logs to native --- lib/native/api/logging.dart | 19 ++- lib/native/frb_generated.dart | 156 ++++++++++++++---- lib/native/frb_generated.io.dart | 18 +++ lib/services/annil/annil.dart | 9 +- lib/services/audio_handler.dart | 5 +- lib/services/logger.dart | 19 +++ lib/services/playback/playback_service.dart | 12 +- lib/ui/page/home/home_action_grid.dart | 4 +- lib/ui/page/search.dart | 1 - lib/ui/page/settings/settings_log.dart | 4 +- rust/Cargo.lock | 3 +- rust/Cargo.toml | 5 +- rust/src/api/logging.rs | 83 ++++++---- rust/src/frb_generated.rs | 170 +++++++++++++++----- 14 files changed, 380 insertions(+), 128 deletions(-) create mode 100644 lib/services/logger.dart diff --git a/lib/native/api/logging.dart b/lib/native/api/logging.dart index 332c833..6adc90d 100644 --- a/lib/native/api/logging.dart +++ b/lib/native/api/logging.dart @@ -11,8 +11,23 @@ import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; void initLogger({required String path}) => RustLib.instance.api.crateApiLoggingInitLogger(path: path); -Future> readLogs({required String path}) => - RustLib.instance.api.crateApiLoggingReadLogs(path: path); +Future> readLogs() => + RustLib.instance.api.crateApiLoggingReadLogs(); + +void logNative( + {required String level, + String? module, + String? file, + int? line, + required String message, + String? stacktace}) => + RustLib.instance.api.crateApiLoggingLogNative( + level: level, + module: module, + file: file, + line: line, + message: message, + stacktace: stacktace); class LogEntry { final String time; diff --git a/lib/native/frb_generated.dart b/lib/native/frb_generated.dart index 0afc05d..579af17 100644 --- a/lib/native/frb_generated.dart +++ b/lib/native/frb_generated.dart @@ -60,7 +60,7 @@ class RustLib extends BaseEntrypoint { String get codegenVersion => '2.1.0'; @override - int get rustContentHash => -803034545; + int get rustContentHash => 854232876; static const kDefaultExternalLibraryLoaderConfig = ExternalLibraryLoaderConfig( @@ -73,7 +73,15 @@ class RustLib extends BaseEntrypoint { abstract class RustLibApi extends BaseApi { void crateApiLoggingInitLogger({required String path}); - Future> crateApiLoggingReadLogs({required String path}); + void crateApiLoggingLogNative( + {required String level, + String? module, + String? file, + int? line, + required String message, + String? stacktace}); + + Future> crateApiLoggingReadLogs(); Future crateApiNetworkNetworkStatusIsOnline( {required NetworkStatus that}); @@ -221,27 +229,60 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { ); @override - Future> crateApiLoggingReadLogs({required String path}) { + void crateApiLoggingLogNative( + {required String level, + String? module, + String? file, + int? line, + required String message, + String? stacktace}) { + return handler.executeSync(SyncTask( + callFfi: () { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(level, serializer); + sse_encode_opt_String(module, serializer); + sse_encode_opt_String(file, serializer); + sse_encode_opt_box_autoadd_u_32(line, serializer); + sse_encode_String(message, serializer); + sse_encode_opt_String(stacktace, serializer); + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2)!; + }, + codec: SseCodec( + decodeSuccessData: sse_decode_unit, + decodeErrorData: sse_decode_AnyhowException, + ), + constMeta: kCrateApiLoggingLogNativeConstMeta, + argValues: [level, module, file, line, message, stacktace], + apiImpl: this, + )); + } + + TaskConstMeta get kCrateApiLoggingLogNativeConstMeta => const TaskConstMeta( + debugName: "log_native", + argNames: ["level", "module", "file", "line", "message", "stacktace"], + ); + + @override + Future> crateApiLoggingReadLogs() { return handler.executeNormal(NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); - sse_encode_String(path, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 2, port: port_); + funcId: 3, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_log_entry, decodeErrorData: sse_decode_AnyhowException, ), constMeta: kCrateApiLoggingReadLogsConstMeta, - argValues: [path], + argValues: [], apiImpl: this, )); } TaskConstMeta get kCrateApiLoggingReadLogsConstMeta => const TaskConstMeta( debugName: "read_logs", - argNames: ["path"], + argNames: [], ); @override @@ -252,7 +293,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_network_status(that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 3, port: port_); + funcId: 4, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -277,7 +318,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_bool(isOnline, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 4, port: port_); + funcId: 5, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -310,7 +351,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(auth, serializer); sse_encode_i_32(priority, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 5, port: port_); + funcId: 6, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -337,7 +378,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnixPlayer( that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 6, port: port_); + funcId: 7, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -362,7 +403,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnixPlayer( that, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 7)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; }, codec: SseCodec( decodeSuccessData: sse_decode_bool, @@ -386,7 +427,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(cachePath, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 8)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 9)!; }, codec: SseCodec( decodeSuccessData: @@ -413,7 +454,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnixPlayer( that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 9, port: port_); + funcId: 10, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -439,7 +480,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnixPlayer( that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 10, port: port_); + funcId: 11, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -468,7 +509,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer); sse_encode_StreamSink_player_state_event_Sse(stream, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 11, port: port_); + funcId: 12, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -498,7 +539,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer); sse_encode_StreamSink_progress_state_Sse(stream, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 12, port: port_); + funcId: 13, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -527,7 +568,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer); sse_encode_u_32(position, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 13, port: port_); + funcId: 14, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -560,7 +601,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_audio_quality(quality, serializer); sse_encode_bool(opus, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 14, port: port_); + funcId: 15, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -588,7 +629,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { that, serializer); sse_encode_f_32(volume, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 15, port: port_); + funcId: 16, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -614,7 +655,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerAnnixPlayer( that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 16, port: port_); + funcId: 17, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -638,7 +679,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(path, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 17)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 18)!; }, codec: SseCodec( decodeSuccessData: sse_decode_u_32, @@ -665,7 +706,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_local_db(that, serializer); sse_encode_Uuid(albumId, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 18, port: port_); + funcId: 19, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -693,7 +734,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(tag, serializer); sse_encode_bool(recursive, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 19, port: port_); + funcId: 20, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_Uuid, @@ -718,7 +759,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_local_db(that, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 20, port: port_); + funcId: 21, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_list_tag_item, @@ -743,7 +784,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(path, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 21, port: port_); + funcId: 22, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_local_db, @@ -769,7 +810,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_local_store(that, serializer); sse_encode_opt_String(category, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 22, port: port_); + funcId: 23, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -799,7 +840,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(category, serializer); sse_encode_String(key, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 23, port: port_); + funcId: 24, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -831,7 +872,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(key, serializer); sse_encode_String(value, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, - funcId: 24, port: port_); + funcId: 25, port: port_); }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -855,7 +896,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(root, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 25)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; }, codec: SseCodec( decodeSuccessData: sse_decode_local_store, @@ -881,7 +922,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_native_preference_store(that, serializer); sse_encode_String(key, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 26)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; }, codec: SseCodec( decodeSuccessData: sse_decode_opt_String, @@ -906,7 +947,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { callFfi: () { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_String(root, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 27)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28)!; }, codec: SseCodec( decodeSuccessData: sse_decode_native_preference_store, @@ -932,7 +973,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_native_preference_store(that, serializer); sse_encode_String(key, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 28)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -958,7 +999,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { final serializer = SseSerializer(generalizedFrbRustBinding); sse_encode_box_autoadd_native_preference_store(that, serializer); sse_encode_String(prefix, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 29)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -987,7 +1028,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_box_autoadd_native_preference_store(that, serializer); sse_encode_String(key, serializer); sse_encode_String(value, serializer); - return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 30)!; + return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 31)!; }, codec: SseCodec( decodeSuccessData: sse_decode_unit, @@ -1135,6 +1176,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return dco_decode_native_preference_store(raw); } + @protected + int dco_decode_box_autoadd_u_32(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw as int; + } + @protected double dco_decode_f_32(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -1252,6 +1299,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw == null ? null : dco_decode_box_autoadd_i_32(raw); } + @protected + int? dco_decode_opt_box_autoadd_u_32(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_box_autoadd_u_32(raw); + } + @protected PlayerStateEvent dco_decode_player_state_event(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -1422,6 +1475,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return (sse_decode_native_preference_store(deserializer)); } + @protected + int sse_decode_box_autoadd_u_32(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + return (sse_decode_u_32(deserializer)); + } + @protected double sse_decode_f_32(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -1560,6 +1619,17 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + int? sse_decode_opt_box_autoadd_u_32(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_box_autoadd_u_32(deserializer)); + } else { + return null; + } + } + @protected PlayerStateEvent sse_decode_player_state_event(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -1735,6 +1805,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_native_preference_store(self, serializer); } + @protected + void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_u_32(self, serializer); + } + @protected void sse_encode_f_32(double self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -1849,6 +1925,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_opt_box_autoadd_u_32(int? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_box_autoadd_u_32(self, serializer); + } + } + @protected void sse_encode_player_state_event( PlayerStateEvent self, SseSerializer serializer) { diff --git a/lib/native/frb_generated.io.dart b/lib/native/frb_generated.io.dart index 3abf8c9..ad96bbd 100644 --- a/lib/native/frb_generated.io.dart +++ b/lib/native/frb_generated.io.dart @@ -92,6 +92,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NativePreferenceStore dco_decode_box_autoadd_native_preference_store( dynamic raw); + @protected + int dco_decode_box_autoadd_u_32(dynamic raw); + @protected double dco_decode_f_32(dynamic raw); @@ -134,6 +137,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int? dco_decode_opt_box_autoadd_i_32(dynamic raw); + @protected + int? dco_decode_opt_box_autoadd_u_32(dynamic raw); + @protected PlayerStateEvent dco_decode_player_state_event(dynamic raw); @@ -214,6 +220,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { NativePreferenceStore sse_decode_box_autoadd_native_preference_store( SseDeserializer deserializer); + @protected + int sse_decode_box_autoadd_u_32(SseDeserializer deserializer); + @protected double sse_decode_f_32(SseDeserializer deserializer); @@ -257,6 +266,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected int? sse_decode_opt_box_autoadd_i_32(SseDeserializer deserializer); + @protected + int? sse_decode_opt_box_autoadd_u_32(SseDeserializer deserializer); + @protected PlayerStateEvent sse_decode_player_state_event(SseDeserializer deserializer); @@ -339,6 +351,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_box_autoadd_native_preference_store( NativePreferenceStore self, SseSerializer serializer); + @protected + void sse_encode_box_autoadd_u_32(int self, SseSerializer serializer); + @protected void sse_encode_f_32(double self, SseSerializer serializer); @@ -383,6 +398,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void sse_encode_opt_box_autoadd_i_32(int? self, SseSerializer serializer); + @protected + void sse_encode_opt_box_autoadd_u_32(int? self, SseSerializer serializer); + @protected void sse_encode_player_state_event( PlayerStateEvent self, SseSerializer serializer); diff --git a/lib/services/annil/annil.dart b/lib/services/annil/annil.dart index d78187f..12d67a9 100644 --- a/lib/services/annil/annil.dart +++ b/lib/services/annil/annil.dart @@ -5,6 +5,7 @@ import 'package:annix/providers.dart'; import 'package:annix/services/anniv/anniv_model.dart'; import 'package:annix/services/annil/cache.dart'; import 'package:annix/services/local/database.dart'; +import 'package:annix/services/logger.dart'; import 'package:annix/services/path.dart'; import 'package:annix/services/playback/playback_service.dart'; import 'package:annix/utils/redirect_interceptor.dart'; @@ -42,7 +43,7 @@ class AnnilService extends ChangeNotifier { client.interceptors.add(RetryInterceptor( dio: client, - logPrint: (final text) => FLog.error(text: text), + logPrint: (final text) => Logger.error(text), retries: 3, retryDelays: const [ Duration(seconds: 1), @@ -337,8 +338,8 @@ class AnnilService extends ChangeNotifier { ), ); final newETag = response.headers['etag']![0]; - FLog.debug( - text: 'Annil cache MISSED, old etag: $etag, new etag: $newETag', + Logger.debug( + 'Annil cache MISSED, old etag: $etag, new etag: $newETag', ); if (etag != newETag) { etags[server.id] = newETag; @@ -361,7 +362,7 @@ class AnnilService extends ChangeNotifier { } } on DioException catch (e) { if (e.response?.statusCode == 304) { - FLog.trace(text: 'Annil cache HIT, etag: $etag'); + Logger.trace('Annil cache HIT, etag: $etag'); } else { etags.remove(server.id); await db.transaction(() async { diff --git a/lib/services/audio_handler.dart b/lib/services/audio_handler.dart index 1c49d1c..042dbfc 100644 --- a/lib/services/audio_handler.dart +++ b/lib/services/audio_handler.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:annix/providers.dart'; import 'package:annix/services/anniv/anniv.dart'; import 'package:annix/services/anniv/anniv_model.dart'; +import 'package:annix/services/logger.dart'; import 'package:annix/services/playback/playback.dart'; import 'package:annix/services/local/database.dart'; import 'package:audio_service/audio_service.dart'; @@ -53,7 +54,7 @@ class AnnixAudioHandler extends BaseAudioHandler { // interruption session.interruptionEventStream.listen((final event) { if (event.begin) { - FLog.info(text: 'handling interruption beginning ${event.type}'); + Logger.info('handling interruption beginning ${event.type}'); switch (event.type) { case AudioInterruptionType.duck: // TODO @@ -65,7 +66,7 @@ class AnnixAudioHandler extends BaseAudioHandler { break; } } else { - FLog.info(text: 'handling interruption end ${event.type}'); + Logger.info('handling interruption end ${event.type}'); switch (event.type) { case AudioInterruptionType.duck: // TODO diff --git a/lib/services/logger.dart b/lib/services/logger.dart new file mode 100644 index 0000000..fe4959e --- /dev/null +++ b/lib/services/logger.dart @@ -0,0 +1,19 @@ +import 'package:annix/native/api/logging.dart'; + +class Logger { + static void error(String message) { + logNative(level: 'ERROR', message: message); + } + + static void info(String message) { + logNative(level: 'INFO', message: message); + } + + static void debug(String message) { + logNative(level: 'DEBUG', message: message); + } + + static void trace(String message) { + logNative(level: 'TRACE', message: message); + } +} diff --git a/lib/services/playback/playback_service.dart b/lib/services/playback/playback_service.dart index a19c325..c08d145 100644 --- a/lib/services/playback/playback_service.dart +++ b/lib/services/playback/playback_service.dart @@ -7,12 +7,12 @@ import 'package:annix/services/annil/audio_source.dart'; import 'package:annix/services/annil/annil.dart'; import 'package:annix/services/anniv/anniv.dart'; import 'package:annix/services/anniv/anniv_model.dart'; +import 'package:annix/services/logger.dart'; import 'package:annix/services/metadata/metadata_model.dart'; import 'package:annix/services/path.dart'; import 'package:annix/services/playback/playback.dart'; import 'package:annix/native/api/player.dart'; import 'package:audio_session/audio_session.dart' hide AVAudioSessionCategory; -import 'package:f_logs/f_logs.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -149,7 +149,7 @@ class PlaybackService extends ChangeNotifier { } if (!reload && !PlaybackService.player.isPlaying()) { - FLog.trace(text: 'Resume playing'); + Logger.trace('Resume playing'); await PlaybackService.player.play(); if (loadedAndPaused) { @@ -166,7 +166,7 @@ class PlaybackService extends ChangeNotifier { } // stop previous playback - FLog.trace(text: 'Start playing'); + Logger.trace('Start playing'); await stop(false); // TODO: move annil logic to rust and remove the workaround @@ -192,7 +192,7 @@ class PlaybackService extends ChangeNotifier { } Future pause() async { - FLog.trace(text: 'Pause playing'); + Logger.trace('Pause playing'); await PlaybackService.player.pause(); // deactivate audio session @@ -281,7 +281,7 @@ class PlaybackService extends ChangeNotifier { } Future seek(final Duration position) async { - FLog.trace(text: 'Seek to position $position'); + Logger.trace('Seek to position $position'); // seek first for ui update playing.updatePosition(position); @@ -307,7 +307,7 @@ class PlaybackService extends ChangeNotifier { } Future jump(final int index) async { - FLog.trace(text: 'Jump to $index in playing queue'); + Logger.trace('Jump to $index in playing queue'); if (queue.isNotEmpty) { final to = index % queue.length; if (to != playingIndex) { diff --git a/lib/ui/page/home/home_action_grid.dart b/lib/ui/page/home/home_action_grid.dart index 045b591..5e4bb22 100644 --- a/lib/ui/page/home/home_action_grid.dart +++ b/lib/ui/page/home/home_action_grid.dart @@ -36,7 +36,9 @@ class HomeActionGrid extends ConsumerWidget { showLoadingDialog(context); ref.read(playbackProvider).fullShuffleMode().then( (final value) { - Navigator.of(context, rootNavigator: true).pop(); + if (context.mounted) { + Navigator.of(context, rootNavigator: true).pop(); + } }, ); }, diff --git a/lib/ui/page/search.dart b/lib/ui/page/search.dart index 3edf354..ff79c08 100644 --- a/lib/ui/page/search.dart +++ b/lib/ui/page/search.dart @@ -76,7 +76,6 @@ class _SearchResultWidget extends HookConsumerWidget { final ValueNotifier isLoading; const _SearchResultWidget({ - super.key, required this.result, required this.isLoading, }); diff --git a/lib/ui/page/settings/settings_log.dart b/lib/ui/page/settings/settings_log.dart index 7076668..a4a920d 100644 --- a/lib/ui/page/settings/settings_log.dart +++ b/lib/ui/page/settings/settings_log.dart @@ -1,5 +1,4 @@ import 'package:annix/native/api/logging.dart'; -import 'package:annix/services/path.dart'; import 'package:annix/ui/route/delegate.dart'; import 'package:f_logs/f_logs.dart'; import 'package:flutter/material.dart'; @@ -110,8 +109,7 @@ class SettingsLogView extends HookConsumerWidget { }, ) : FutureBuilder>( - future: readLogs(path: logPath()) - .then((logs) => logs.reversed.toList()), + future: readLogs().then((logs) => logs.reversed.toList()), builder: (final context, final snapshot) { if (snapshot.hasData) { return ListView.builder( diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 19e2c38..a5ac1b4 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -2754,8 +2754,7 @@ dependencies = [ [[package]] name = "tracing-subscriber-sqlite" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219c00ed12939e3ced5fece83be1856b1baeda9b5796727fcd4cd5f2e6978db" +source = "git+https://github.com/ProjectAnni/tracing-subscriber-sqlite?rev=42e79729fae0cb2803b8b9cebb01b039d30f0c9a#42e79729fae0cb2803b8b9cebb01b039d30f0c9a" dependencies = [ "rusqlite", "serde_json", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index adaf22d..40ad087 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -22,7 +22,10 @@ cpal = { version = "0.15.3", features = ["oboe-shared-stdcxx"] } rand = "0.8.5" material-colors = { version = "0.3.3", features = ["image"] } -tracing-subscriber-sqlite = { version = "0.1", features = ["tracing-log"] } +# TODO: upgrade version +tracing-subscriber-sqlite = { git = "https://github.com/ProjectAnni/tracing-subscriber-sqlite", features = [ + "tracing-log", +], rev = "42e79729fae0cb2803b8b9cebb01b039d30f0c9a" } tracing = "0.1.40" tracing-log = "0.2" diff --git a/rust/src/api/logging.rs b/rust/src/api/logging.rs index f9d8931..caf5e70 100644 --- a/rust/src/api/logging.rs +++ b/rust/src/api/logging.rs @@ -1,25 +1,37 @@ +use std::collections::HashMap; + use flutter_rust_bridge::frb; +use once_cell::sync::OnceCell; use rusqlite::Connection; -use rusqlite::Result; use tracing::level_filters::LevelFilter; +pub use tracing_subscriber_sqlite::LogEntry; +use tracing_subscriber_sqlite::LogHandle; + +static LOGGER: OnceCell = OnceCell::new(); #[frb(sync)] pub fn init_logger(path: String) { - let conn = Connection::open(path).unwrap(); + LOGGER.get_or_init(|| { + let conn = Connection::open(path).unwrap(); - tracing_log::LogTracer::init().unwrap(); - tracing::subscriber::set_global_default( - tracing_subscriber_sqlite::SubscriberBuilder::new() + let subscriber = tracing_subscriber_sqlite::SubscriberBuilder::new() .with_max_level(LevelFilter::DEBUG) .with_black_list(["h2"]) .build_prepared(conn) - .unwrap(), - ) - .unwrap(); + .unwrap(); + + let logger = subscriber.log_handle(); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + tracing_log::LogTracer::init().unwrap(); + + logger + }); } #[derive(Debug)] -pub struct LogEntry { +#[frb(mirror(LogEntry))] +pub struct _LogEntry { pub time: String, pub level: String, pub module: Option, @@ -29,22 +41,39 @@ pub struct LogEntry { pub structured: String, } -pub fn read_logs(path: String) -> Result> { - let conn = Connection::open(path)?; - - let mut stmt = conn.prepare("SELECT * FROM logs_v0")?; - let log_iter = stmt.query_map([], |row| { - Ok(LogEntry { - time: row.get(0)?, - level: row.get(1)?, - module: row.get(2)?, - file: row.get(3)?, - line: row.get(4)?, - message: row.get(5)?, - structured: row.get(6)?, - }) - })?; - - let logs: Result> = log_iter.collect(); - logs +pub fn read_logs() -> anyhow::Result> { + let handle = LOGGER + .get() + .ok_or_else(|| anyhow::anyhow!("Logger not initialized"))?; + let logs = handle.read_logs_v0()?; + Ok(logs) +} + +#[frb(sync)] +pub fn log_native( + level: String, + module: Option, + file: Option, + line: Option, + message: String, + stacktace: Option, +) -> anyhow::Result<()> { + let logger = LOGGER + .get() + .ok_or_else(|| anyhow::anyhow!("Logger not initialized"))?; + + let mut kvs = HashMap::new(); + if let Some(stacktace) = stacktace { + kvs.insert("stacktace", stacktace); + } + + logger.log_v0( + &level, + module.as_deref(), + file.as_deref(), + line, + &message, + kvs, + ); + Ok(()) } diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 5ab0596..1fa1c28 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -39,7 +39,7 @@ flutter_rust_bridge::frb_generated_boilerplate!( default_rust_auto_opaque = RustAutoOpaqueMoi, ); pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.1.0"; -pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = -803034545; +pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 854232876; // Section: executor @@ -79,6 +79,50 @@ fn wire__crate__api__logging__init_logger_impl( }, ) } +fn wire__crate__api__logging__log_native_impl( + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) -> flutter_rust_bridge::for_generated::WireSyncRust2DartSse { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_sync::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "log_native", + port: None, + mode: flutter_rust_bridge::for_generated::FfiCallMode::Sync, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_level = ::sse_decode(&mut deserializer); + let api_module = >::sse_decode(&mut deserializer); + let api_file = >::sse_decode(&mut deserializer); + let api_line = >::sse_decode(&mut deserializer); + let api_message = ::sse_decode(&mut deserializer); + let api_stacktace = >::sse_decode(&mut deserializer); + deserializer.end(); + transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( + (move || { + let output_ok = crate::api::logging::log_native( + api_level, + api_module, + api_file, + api_line, + api_message, + api_stacktace, + )?; + Ok(output_ok) + })(), + ) + }, + ) +} fn wire__crate__api__logging__read_logs_impl( port_: flutter_rust_bridge::for_generated::MessagePort, ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, @@ -101,12 +145,11 @@ fn wire__crate__api__logging__read_logs_impl( }; let mut deserializer = flutter_rust_bridge::for_generated::SseDeserializer::new(message); - let api_path = ::sse_decode(&mut deserializer); deserializer.end(); move |context| { transform_result_sse::<_, flutter_rust_bridge::for_generated::anyhow::Error>( (move || { - let output_ok = crate::api::logging::read_logs(api_path)?; + let output_ok = crate::api::logging::read_logs()?; Ok(output_ok) })(), ) @@ -1297,6 +1340,20 @@ fn wire__crate__api__simple__native_preference_store_set_impl( ) } +// Section: static_checks + +#[allow(clippy::unnecessary_literal_unwrap)] +const _: fn() = || { + let LogEntry = None::.unwrap(); + let _: String = LogEntry.time; + let _: String = LogEntry.level; + let _: Option = LogEntry.module; + let _: Option = LogEntry.file; + let _: Option = LogEntry.line; + let _: String = LogEntry.message; + let _: String = LogEntry.structured; +}; + // Section: related_funcs flutter_rust_bridge::frb_generated_moi_arc_impl_value!(Mutex); @@ -1565,6 +1622,17 @@ impl SseDecode for Option { } } +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + impl SseDecode for crate::api::player::PlayerStateEvent { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -1637,62 +1705,62 @@ fn pde_ffi_dispatcher_primary_impl( ) { // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { - 2 => wire__crate__api__logging__read_logs_impl(port, ptr, rust_vec_len, data_len), - 3 => wire__crate__api__network__network_status_is_online_impl( + 3 => wire__crate__api__logging__read_logs_impl(port, ptr, rust_vec_len, data_len), + 4 => wire__crate__api__network__network_status_is_online_impl( port, ptr, rust_vec_len, data_len, ), - 4 => { + 5 => { wire__crate__api__network__update_network_status_impl(port, ptr, rust_vec_len, data_len) } - 5 => wire__crate__api__player__AnnixPlayer_add_provider_impl( + 6 => wire__crate__api__player__AnnixPlayer_add_provider_impl( port, ptr, rust_vec_len, data_len, ), - 6 => wire__crate__api__player__AnnixPlayer_clear_provider_impl( + 7 => wire__crate__api__player__AnnixPlayer_clear_provider_impl( port, ptr, rust_vec_len, data_len, ), - 9 => wire__crate__api__player__AnnixPlayer_pause_impl(port, ptr, rust_vec_len, data_len), - 10 => wire__crate__api__player__AnnixPlayer_play_impl(port, ptr, rust_vec_len, data_len), - 11 => wire__crate__api__player__AnnixPlayer_player_state_stream_impl( + 10 => wire__crate__api__player__AnnixPlayer_pause_impl(port, ptr, rust_vec_len, data_len), + 11 => wire__crate__api__player__AnnixPlayer_play_impl(port, ptr, rust_vec_len, data_len), + 12 => wire__crate__api__player__AnnixPlayer_player_state_stream_impl( port, ptr, rust_vec_len, data_len, ), - 12 => wire__crate__api__player__AnnixPlayer_progress_stream_impl( + 13 => wire__crate__api__player__AnnixPlayer_progress_stream_impl( port, ptr, rust_vec_len, data_len, ), - 13 => wire__crate__api__player__AnnixPlayer_seek_impl(port, ptr, rust_vec_len, data_len), - 14 => { + 14 => wire__crate__api__player__AnnixPlayer_seek_impl(port, ptr, rust_vec_len, data_len), + 15 => { wire__crate__api__player__AnnixPlayer_set_track_impl(port, ptr, rust_vec_len, data_len) } - 15 => { + 16 => { wire__crate__api__player__AnnixPlayer_set_volume_impl(port, ptr, rust_vec_len, data_len) } - 16 => wire__crate__api__player__AnnixPlayer_stop_impl(port, ptr, rust_vec_len, data_len), - 18 => wire__crate__api__simple__local_db_get_album_impl(port, ptr, rust_vec_len, data_len), - 19 => wire__crate__api__simple__local_db_get_albums_by_tag_impl( + 17 => wire__crate__api__player__AnnixPlayer_stop_impl(port, ptr, rust_vec_len, data_len), + 19 => wire__crate__api__simple__local_db_get_album_impl(port, ptr, rust_vec_len, data_len), + 20 => wire__crate__api__simple__local_db_get_albums_by_tag_impl( port, ptr, rust_vec_len, data_len, ), - 20 => wire__crate__api__simple__local_db_get_tags_impl(port, ptr, rust_vec_len, data_len), - 21 => wire__crate__api__simple__local_db_new_impl(port, ptr, rust_vec_len, data_len), - 22 => wire__crate__api__simple__local_store_clear_impl(port, ptr, rust_vec_len, data_len), - 23 => wire__crate__api__simple__local_store_get_impl(port, ptr, rust_vec_len, data_len), - 24 => wire__crate__api__simple__local_store_insert_impl(port, ptr, rust_vec_len, data_len), + 21 => wire__crate__api__simple__local_db_get_tags_impl(port, ptr, rust_vec_len, data_len), + 22 => wire__crate__api__simple__local_db_new_impl(port, ptr, rust_vec_len, data_len), + 23 => wire__crate__api__simple__local_store_clear_impl(port, ptr, rust_vec_len, data_len), + 24 => wire__crate__api__simple__local_store_get_impl(port, ptr, rust_vec_len, data_len), + 25 => wire__crate__api__simple__local_store_insert_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -1706,27 +1774,28 @@ fn pde_ffi_dispatcher_sync_impl( // Codec=Pde (Serialization + dispatch), see doc to use other codecs match func_id { 1 => wire__crate__api__logging__init_logger_impl(ptr, rust_vec_len, data_len), - 7 => wire__crate__api__player__AnnixPlayer_is_playing_impl(ptr, rust_vec_len, data_len), - 8 => wire__crate__api__player__AnnixPlayer_new_impl(ptr, rust_vec_len, data_len), - 17 => wire__crate__api__simple__get_theme_color_impl(ptr, rust_vec_len, data_len), - 25 => wire__crate__api__simple__local_store_new_impl(ptr, rust_vec_len, data_len), - 26 => { + 2 => wire__crate__api__logging__log_native_impl(ptr, rust_vec_len, data_len), + 8 => wire__crate__api__player__AnnixPlayer_is_playing_impl(ptr, rust_vec_len, data_len), + 9 => wire__crate__api__player__AnnixPlayer_new_impl(ptr, rust_vec_len, data_len), + 18 => wire__crate__api__simple__get_theme_color_impl(ptr, rust_vec_len, data_len), + 26 => wire__crate__api__simple__local_store_new_impl(ptr, rust_vec_len, data_len), + 27 => { wire__crate__api__simple__native_preference_store_get_impl(ptr, rust_vec_len, data_len) } - 27 => { + 28 => { wire__crate__api__simple__native_preference_store_new_impl(ptr, rust_vec_len, data_len) } - 28 => wire__crate__api__simple__native_preference_store_remove_impl( + 29 => wire__crate__api__simple__native_preference_store_remove_impl( ptr, rust_vec_len, data_len, ), - 29 => wire__crate__api__simple__native_preference_store_remove_prefix_impl( + 30 => wire__crate__api__simple__native_preference_store_remove_prefix_impl( ptr, rust_vec_len, data_len, ), - 30 => { + 31 => { wire__crate__api__simple__native_preference_store_set_impl(ptr, rust_vec_len, data_len) } _ => unreachable!(), @@ -1805,26 +1874,29 @@ impl flutter_rust_bridge::IntoIntoDart } } // Codec=Dco (DartCObject based), see doc to use other codecs -impl flutter_rust_bridge::IntoDart for crate::api::logging::LogEntry { +impl flutter_rust_bridge::IntoDart for FrbWrapper { fn into_dart(self) -> flutter_rust_bridge::for_generated::DartAbi { [ - self.time.into_into_dart().into_dart(), - self.level.into_into_dart().into_dart(), - self.module.into_into_dart().into_dart(), - self.file.into_into_dart().into_dart(), - self.line.into_into_dart().into_dart(), - self.message.into_into_dart().into_dart(), - self.structured.into_into_dart().into_dart(), + self.0.time.into_into_dart().into_dart(), + self.0.level.into_into_dart().into_dart(), + self.0.module.into_into_dart().into_dart(), + self.0.file.into_into_dart().into_dart(), + self.0.line.into_into_dart().into_dart(), + self.0.message.into_into_dart().into_dart(), + self.0.structured.into_into_dart().into_dart(), ] .into_dart() } } -impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive for crate::api::logging::LogEntry {} -impl flutter_rust_bridge::IntoIntoDart +impl flutter_rust_bridge::for_generated::IntoDartExceptPrimitive + for FrbWrapper +{ +} +impl flutter_rust_bridge::IntoIntoDart> for crate::api::logging::LogEntry { - fn into_into_dart(self) -> crate::api::logging::LogEntry { - self + fn into_into_dart(self) -> FrbWrapper { + self.into() } } // Codec=Dco (DartCObject based), see doc to use other codecs @@ -2164,6 +2236,16 @@ impl SseEncode for Option { } } +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + impl SseEncode for crate::api::player::PlayerStateEvent { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {