From 2cf1c5f4e96ec25353fea6a388dc33412ec5bc43 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Fri, 1 Mar 2024 16:25:56 -0500 Subject: [PATCH] better logging --- .../account_repository.dart | 9 +- .../new_account_page/new_account_page.dart | 2 +- lib/chat/cubits/messages_cubit.dart | 55 +++---- packages/veilid_support/lib/src/config.dart | 33 ++-- packages/veilid_support/lib/src/identity.dart | 148 +++++++++--------- .../veilid_support/lib/src/veilid_log.dart | 14 +- .../veilid_support/lib/veilid_support.dart | 2 +- pubspec.lock | 2 +- pubspec.yaml | 2 +- 9 files changed, 147 insertions(+), 120 deletions(-) diff --git a/lib/account_manager/repository/account_repository/account_repository.dart b/lib/account_manager/repository/account_repository/account_repository.dart index 872393e..1b145b3 100644 --- a/lib/account_manager/repository/account_repository/account_repository.dart +++ b/lib/account_manager/repository/account_repository/account_repository.dart @@ -178,7 +178,9 @@ class AccountRepository { /// Creates a new master identity, an account associated with the master /// identity, stores the account in the identity key and then logs into /// that account with no password set at this time - Future createMasterIdentity(NewProfileSpec newProfileSpec) async { + Future createWithNewMasterIdentity( + NewProfileSpec newProfileSpec) async { + log.debug('Creating master identity'); final imws = await IdentityMasterWithSecrets.create(); try { final localAccount = await _newLocalAccount( @@ -204,6 +206,8 @@ class AccountRepository { required NewProfileSpec newProfileSpec, EncryptionKeyType encryptionKeyType = EncryptionKeyType.none, String encryptionKey = ''}) async { + log.debug('Creating new local account'); + final localAccounts = await _localAccounts.get(); // Add account with profile to DHT @@ -212,15 +216,18 @@ class AccountRepository { accountKey: veilidChatAccountKey, createAccountCallback: (parent) async { // Make empty contact list + log.debug('Creating contacts list'); final contactList = await (await DHTShortArray.create(parent: parent)) .scope((r) async => r.record.ownedDHTRecordPointer); // Make empty contact invitation record list + log.debug('Creating contact invitation records list'); final contactInvitationRecords = await (await DHTShortArray.create(parent: parent)) .scope((r) async => r.record.ownedDHTRecordPointer); // Make empty chat record list + log.debug('Creating chat records list'); final chatRecords = await (await DHTShortArray.create(parent: parent)) .scope((r) async => r.record.ownedDHTRecordPointer); diff --git a/lib/account_manager/views/new_account_page/new_account_page.dart b/lib/account_manager/views/new_account_page/new_account_page.dart index b57c5fa..b249a99 100644 --- a/lib/account_manager/views/new_account_page/new_account_page.dart +++ b/lib/account_manager/views/new_account_page/new_account_page.dart @@ -122,7 +122,7 @@ class NewAccountPageState extends State { NewProfileSpec(name: name, pronouns: pronouns); await AccountRepository.instance - .createMasterIdentity(newProfileSpec); + .createWithNewMasterIdentity(newProfileSpec); } on Exception catch (e) { if (context.mounted) { await showErrorModal(context, translate('new_account_page.error'), diff --git a/lib/chat/cubits/messages_cubit.dart b/lib/chat/cubits/messages_cubit.dart index c1528de..ee259dd 100644 --- a/lib/chat/cubits/messages_cubit.dart +++ b/lib/chat/cubits/messages_cubit.dart @@ -25,29 +25,20 @@ class MessagesCubit extends Cubit>> { required TypedKey remoteConversationRecordKey, required TypedKey remoteMessagesRecordKey}) : _activeAccountInfo = activeAccountInfo, - _localMessagesRecordKey = localMessagesRecordKey, _remoteIdentityPublicKey = remoteIdentityPublicKey, - _remoteMessagesRecordKey = remoteMessagesRecordKey, _remoteMessagesQueue = StreamController(), super(const AsyncValue.loading()) { // Local messages key - Future.delayed(Duration.zero, () async { - final crypto = await getMessagesCrypto(); - final writer = _activeAccountInfo.conversationWriter; - final record = await DHTShortArray.openWrite( - _localMessagesRecordKey, writer, - parent: localConversationRecordKey, crypto: crypto); - await _setLocalMessages(record); - }); + Future.delayed( + Duration.zero, + () async => _initLocalMessages( + localConversationRecordKey, localMessagesRecordKey)); // Remote messages key - Future.delayed(Duration.zero, () async { - // Open remote record key if it is specified - final crypto = await getMessagesCrypto(); - final record = await DHTShortArray.openRead(_remoteMessagesRecordKey, - parent: remoteConversationRecordKey, crypto: crypto); - await _setRemoteMessages(record); - }); + Future.delayed( + Duration.zero, + () async => _initRemoteMessages( + remoteConversationRecordKey, remoteMessagesRecordKey)); // Remote messages listener Future.delayed(Duration.zero, () async { @@ -59,8 +50,11 @@ class MessagesCubit extends Cubit>> { @override Future close() async { + await _remoteMessagesQueue.close(); await _localSubscription?.cancel(); await _remoteSubscription?.cancel(); + await _localMessagesCubit?.close(); + await _remoteMessagesCubit?.close(); await super.close(); } @@ -129,20 +123,29 @@ class MessagesCubit extends Cubit>> { } // Open local messages key - Future _setLocalMessages(DHTShortArray localMessagesRecord) async { - assert(_localMessagesCubit == null, 'shoud not set local messages twice'); - _localMessagesCubit = DHTShortArrayCubit.value( - shortArray: localMessagesRecord, + Future _initLocalMessages(TypedKey localConversationRecordKey, + TypedKey localMessagesRecordKey) async { + final crypto = await getMessagesCrypto(); + final writer = _activeAccountInfo.conversationWriter; + + _localMessagesCubit = DHTShortArrayCubit( + open: () async => DHTShortArray.openWrite( + localMessagesRecordKey, writer, + parent: localConversationRecordKey, crypto: crypto), decodeElement: proto.Message.fromBuffer); _localSubscription = _localMessagesCubit!.stream.listen(updateLocalMessagesState); } // Open remote messages key - Future _setRemoteMessages(DHTShortArray remoteMessagesRecord) async { - assert(_remoteMessagesCubit == null, 'shoud not set remote messages twice'); - _remoteMessagesCubit = DHTShortArrayCubit.value( - shortArray: remoteMessagesRecord, + Future _initRemoteMessages(TypedKey remoteConversationRecordKey, + TypedKey remoteMessagesRecordKey) async { + // Open remote record key if it is specified + final crypto = await getMessagesCrypto(); + + _remoteMessagesCubit = DHTShortArrayCubit( + open: () async => DHTShortArray.openRead(remoteMessagesRecordKey, + parent: remoteConversationRecordKey, crypto: crypto), decodeElement: proto.Message.fromBuffer); _remoteSubscription = _remoteMessagesCubit!.stream.listen(updateRemoteMessagesState); @@ -208,8 +211,6 @@ class MessagesCubit extends Cubit>> { final ActiveAccountInfo _activeAccountInfo; final TypedKey _remoteIdentityPublicKey; - final TypedKey _localMessagesRecordKey; - final TypedKey _remoteMessagesRecordKey; DHTShortArrayCubit? _localMessagesCubit; DHTShortArrayCubit? _remoteMessagesCubit; final StreamController<_MessageQueueEntry> _remoteMessagesQueue; diff --git a/packages/veilid_support/lib/src/config.dart b/packages/veilid_support/lib/src/config.dart index 1d2b521..dff9f3e 100644 --- a/packages/veilid_support/lib/src/config.dart +++ b/packages/veilid_support/lib/src/config.dart @@ -2,31 +2,44 @@ import 'package:veilid/veilid.dart'; Map getDefaultVeilidPlatformConfig( bool isWeb, String appName) { + final ignoreLogTargetsStr = + // ignore: do_not_use_environment + const String.fromEnvironment('IGNORE_LOG_TARGETS').trim(); + final ignoreLogTargets = ignoreLogTargetsStr.isEmpty + ? [] + : ignoreLogTargetsStr.split(',').map((e) => e.trim()).toList(); + if (isWeb) { - return const VeilidWASMConfig( + return VeilidWASMConfig( logging: VeilidWASMConfigLogging( performance: VeilidWASMConfigLoggingPerformance( enabled: true, level: VeilidConfigLogLevel.debug, logsInTimings: true, - logsInConsole: false), + logsInConsole: false, + ignoreLogTargets: ignoreLogTargets), api: VeilidWASMConfigLoggingApi( - enabled: true, level: VeilidConfigLogLevel.info))) + enabled: true, + level: VeilidConfigLogLevel.info, + ignoreLogTargets: ignoreLogTargets))) .toJson(); } return VeilidFFIConfig( logging: VeilidFFIConfigLogging( - terminal: const VeilidFFIConfigLoggingTerminal( - enabled: false, - level: VeilidConfigLogLevel.debug, - ), + terminal: VeilidFFIConfigLoggingTerminal( + enabled: false, + level: VeilidConfigLogLevel.debug, + ignoreLogTargets: ignoreLogTargets), otlp: VeilidFFIConfigLoggingOtlp( enabled: false, level: VeilidConfigLogLevel.trace, grpcEndpoint: '127.0.0.1:4317', - serviceName: appName), - api: const VeilidFFIConfigLoggingApi( - enabled: true, level: VeilidConfigLogLevel.info))) + serviceName: appName, + ignoreLogTargets: ignoreLogTargets), + api: VeilidFFIConfigLoggingApi( + enabled: true, + level: VeilidConfigLogLevel.info, + ignoreLogTargets: ignoreLogTargets))) .toJson(); } diff --git a/packages/veilid_support/lib/src/identity.dart b/packages/veilid_support/lib/src/identity.dart index 70dc295..63361c7 100644 --- a/packages/veilid_support/lib/src/identity.dart +++ b/packages/veilid_support/lib/src/identity.dart @@ -3,9 +3,9 @@ import 'dart:typed_data'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:protobuf/protobuf.dart'; -import 'package:veilid/veilid.dart'; -import '../dht_support/dht_support.dart'; +import '../veilid_support.dart'; +import 'veilid_log.dart'; part 'identity.freezed.dart'; part 'identity.g.dart'; @@ -161,42 +161,44 @@ extension IdentityMasterExtension on IdentityMaster { /////// Add account with profile to DHT // Open identity key for writing + veilidLoggy.debug('Opening master identity'); return (await pool.openWrite( identityRecordKey, identityWriter(identitySecret), parent: masterRecordKey)) - .scope((identityRec) async => - // Create new account to insert into identity - (await pool.create(parent: identityRec.key)) - .deleteScope((accountRec) async { - final account = await createAccountCallback(accountRec.key); - // Write account key - await accountRec.eventualWriteProtobuf(account); + .scope((identityRec) async { + // Create new account to insert into identity + veilidLoggy.debug('Creating new account'); + return (await pool.create(parent: identityRec.key)) + .deleteScope((accountRec) async { + final account = await createAccountCallback(accountRec.key); + // Write account key + veilidLoggy.debug('Writing account record'); + await accountRec.eventualWriteProtobuf(account); - // Update identity key to include account - final newAccountRecordInfo = AccountRecordInfo( - accountRecord: OwnedDHTRecordPointer( - recordKey: accountRec.key, - owner: accountRec.ownerKeyPair!)); + // Update identity key to include account + final newAccountRecordInfo = AccountRecordInfo( + accountRecord: OwnedDHTRecordPointer( + recordKey: accountRec.key, owner: accountRec.ownerKeyPair!)); - await identityRec.eventualUpdateJson(Identity.fromJson, - (oldIdentity) async { - if (oldIdentity == null) { - throw IdentityException.readError; - } - final oldAccountRecords = - IMapOfSets.from(oldIdentity.accountRecords); + veilidLoggy.debug('Updating identity with new account'); + await identityRec.eventualUpdateJson(Identity.fromJson, + (oldIdentity) async { + if (oldIdentity == null) { + throw IdentityException.readError; + } + final oldAccountRecords = IMapOfSets.from(oldIdentity.accountRecords); - if (oldAccountRecords.get(accountKey).length >= maxAccounts) { - throw IdentityException.limitExceeded; - } - final accountRecords = oldAccountRecords - .add(accountKey, newAccountRecordInfo) - .asIMap(); - return oldIdentity.copyWith(accountRecords: accountRecords); - }); + if (oldAccountRecords.get(accountKey).length >= maxAccounts) { + throw IdentityException.limitExceeded; + } + final accountRecords = + oldAccountRecords.add(accountKey, newAccountRecordInfo).asIMap(); + return oldIdentity.copyWith(accountRecords: accountRecords); + }); - return newAccountRecordInfo; - })); + return newAccountRecordInfo; + }); + }); } } @@ -219,56 +221,58 @@ class IdentityMasterWithSecrets { final pool = DHTRecordPool.instance; // IdentityMaster DHT record is public/unencrypted + veilidLoggy.debug('Creating master identity record'); return (await pool.create(crypto: const DHTRecordCryptoPublic())) - .deleteScope((masterRec) async => - // Identity record is private - (await pool.create(parent: masterRec.key)) - .scope((identityRec) async { - // Make IdentityMaster - final masterRecordKey = masterRec.key; - final masterOwner = masterRec.ownerKeyPair!; - final masterSigBuf = BytesBuilder() - ..add(masterRecordKey.decode()) - ..add(masterOwner.key.decode()); + .deleteScope((masterRec) async { + veilidLoggy.debug('Creating identity record'); + // Identity record is private + return (await pool.create(parent: masterRec.key)) + .scope((identityRec) async { + // Make IdentityMaster + final masterRecordKey = masterRec.key; + final masterOwner = masterRec.ownerKeyPair!; + final masterSigBuf = BytesBuilder() + ..add(masterRecordKey.decode()) + ..add(masterOwner.key.decode()); - final identityRecordKey = identityRec.key; - final identityOwner = identityRec.ownerKeyPair!; - final identitySigBuf = BytesBuilder() - ..add(identityRecordKey.decode()) - ..add(identityOwner.key.decode()); + final identityRecordKey = identityRec.key; + final identityOwner = identityRec.ownerKeyPair!; + final identitySigBuf = BytesBuilder() + ..add(identityRecordKey.decode()) + ..add(identityOwner.key.decode()); - assert(masterRecordKey.kind == identityRecordKey.kind, - 'new master and identity should have same cryptosystem'); - final crypto = - await pool.veilid.getCryptoSystem(masterRecordKey.kind); + assert(masterRecordKey.kind == identityRecordKey.kind, + 'new master and identity should have same cryptosystem'); + final crypto = await pool.veilid.getCryptoSystem(masterRecordKey.kind); - final identitySignature = await crypto.signWithKeyPair( - masterOwner, identitySigBuf.toBytes()); - final masterSignature = await crypto.signWithKeyPair( - identityOwner, masterSigBuf.toBytes()); + final identitySignature = + await crypto.signWithKeyPair(masterOwner, identitySigBuf.toBytes()); + final masterSignature = + await crypto.signWithKeyPair(identityOwner, masterSigBuf.toBytes()); - final identityMaster = IdentityMaster( - identityRecordKey: identityRecordKey, - identityPublicKey: identityOwner.key, - masterRecordKey: masterRecordKey, - masterPublicKey: masterOwner.key, - identitySignature: identitySignature, - masterSignature: masterSignature); + final identityMaster = IdentityMaster( + identityRecordKey: identityRecordKey, + identityPublicKey: identityOwner.key, + masterRecordKey: masterRecordKey, + masterPublicKey: masterOwner.key, + identitySignature: identitySignature, + masterSignature: masterSignature); - // Write identity master to master dht key - await masterRec.eventualWriteJson(identityMaster); + // Write identity master to master dht key + await masterRec.eventualWriteJson(identityMaster); - // Make empty identity - const identity = Identity(accountRecords: IMapConst({})); + // Make empty identity + const identity = Identity(accountRecords: IMapConst({})); - // Write empty identity to identity dht key - await identityRec.eventualWriteJson(identity); + // Write empty identity to identity dht key + await identityRec.eventualWriteJson(identity); - return IdentityMasterWithSecrets._( - identityMaster: identityMaster, - masterSecret: masterOwner.secret, - identitySecret: identityOwner.secret); - })); + return IdentityMasterWithSecrets._( + identityMaster: identityMaster, + masterSecret: masterOwner.secret, + identitySecret: identityOwner.secret); + }); + }); } } diff --git a/packages/veilid_support/lib/src/veilid_log.dart b/packages/veilid_support/lib/src/veilid_log.dart index f5db930..fbabc70 100644 --- a/packages/veilid_support/lib/src/veilid_log.dart +++ b/packages/veilid_support/lib/src/veilid_log.dart @@ -1,4 +1,5 @@ import 'package:loggy/loggy.dart'; +import 'package:meta/meta.dart'; import 'package:veilid/veilid.dart'; // Loggy tools @@ -37,7 +38,8 @@ class VeilidLoggy implements LoggyType { Loggy get loggy => Loggy('Veilid'); } -Loggy get _veilidLoggy => Loggy('Veilid'); +@internal +Loggy get veilidLoggy => Loggy('Veilid'); void processLog(VeilidLog log) { StackTrace? stackTrace; @@ -50,19 +52,19 @@ void processLog(VeilidLog log) { switch (log.logLevel) { case VeilidLogLevel.error: - _veilidLoggy.error(log.message, error, stackTrace); + veilidLoggy.error(log.message, error, stackTrace); break; case VeilidLogLevel.warn: - _veilidLoggy.warning(log.message, error, stackTrace); + veilidLoggy.warning(log.message, error, stackTrace); break; case VeilidLogLevel.info: - _veilidLoggy.info(log.message, error, stackTrace); + veilidLoggy.info(log.message, error, stackTrace); break; case VeilidLogLevel.debug: - _veilidLoggy.debug(log.message, error, stackTrace); + veilidLoggy.debug(log.message, error, stackTrace); break; case VeilidLogLevel.trace: - _veilidLoggy.trace(log.message, error, stackTrace); + veilidLoggy.trace(log.message, error, stackTrace); break; } } diff --git a/packages/veilid_support/lib/veilid_support.dart b/packages/veilid_support/lib/veilid_support.dart index f9e9293..56db796 100644 --- a/packages/veilid_support/lib/veilid_support.dart +++ b/packages/veilid_support/lib/veilid_support.dart @@ -12,4 +12,4 @@ export 'src/json_tools.dart'; export 'src/memory_tools.dart'; export 'src/protobuf_tools.dart'; export 'src/table_db.dart'; -export 'src/veilid_log.dart'; +export 'src/veilid_log.dart' hide veilidLoggy; diff --git a/pubspec.lock b/pubspec.lock index 2a2bec9..c1c3af8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1618,4 +1618,4 @@ packages: version: "1.1.2" sdks: dart: ">=3.3.0 <4.0.0" - flutter: ">=3.19.0" + flutter: ">=3.19.1" diff --git a/pubspec.yaml b/pubspec.yaml index 8b2341d..6fa782e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ version: 1.0.2+0 environment: sdk: '>=3.2.0 <4.0.0' - flutter: ">=3.10.0" + flutter: '>=3.19.1' dependencies: animated_theme_switcher: ^2.0.10