better logging

This commit is contained in:
Christien Rioux 2024-03-01 16:25:56 -05:00
parent f896fc822c
commit 2cf1c5f4e9
9 changed files with 147 additions and 120 deletions

View File

@ -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<void> createMasterIdentity(NewProfileSpec newProfileSpec) async {
Future<void> 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);

View File

@ -122,7 +122,7 @@ class NewAccountPageState extends State<NewAccountPage> {
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'),

View File

@ -25,29 +25,20 @@ class MessagesCubit extends Cubit<AsyncValue<IList<proto.Message>>> {
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<AsyncValue<IList<proto.Message>>> {
@override
Future<void> 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<AsyncValue<IList<proto.Message>>> {
}
// Open local messages key
Future<void> _setLocalMessages(DHTShortArray localMessagesRecord) async {
assert(_localMessagesCubit == null, 'shoud not set local messages twice');
_localMessagesCubit = DHTShortArrayCubit.value(
shortArray: localMessagesRecord,
Future<void> _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<void> _setRemoteMessages(DHTShortArray remoteMessagesRecord) async {
assert(_remoteMessagesCubit == null, 'shoud not set remote messages twice');
_remoteMessagesCubit = DHTShortArrayCubit.value(
shortArray: remoteMessagesRecord,
Future<void> _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<AsyncValue<IList<proto.Message>>> {
final ActiveAccountInfo _activeAccountInfo;
final TypedKey _remoteIdentityPublicKey;
final TypedKey _localMessagesRecordKey;
final TypedKey _remoteMessagesRecordKey;
DHTShortArrayCubit<proto.Message>? _localMessagesCubit;
DHTShortArrayCubit<proto.Message>? _remoteMessagesCubit;
final StreamController<_MessageQueueEntry> _remoteMessagesQueue;

View File

@ -2,31 +2,44 @@ import 'package:veilid/veilid.dart';
Map<String, dynamic> getDefaultVeilidPlatformConfig(
bool isWeb, String appName) {
final ignoreLogTargetsStr =
// ignore: do_not_use_environment
const String.fromEnvironment('IGNORE_LOG_TARGETS').trim();
final ignoreLogTargets = ignoreLogTargetsStr.isEmpty
? <String>[]
: 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();
}

View File

@ -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);
});
});
}
}

View File

@ -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<VeilidLoggy> get loggy => Loggy<VeilidLoggy>('Veilid');
}
Loggy get _veilidLoggy => Loggy<VeilidLoggy>('Veilid');
@internal
Loggy get veilidLoggy => Loggy<VeilidLoggy>('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;
}
}

View File

@ -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;

View File

@ -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"

View File

@ -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