add proper logging

This commit is contained in:
shenlong-tanwen
2024-08-21 23:43:48 +05:30
parent 1631df70e9
commit 75448ce56b
37 changed files with 923 additions and 224 deletions
@@ -2,10 +2,14 @@ import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
// ignore: depend_on_referenced_packages
import 'package:drift_dev/api/migrations.dart';
import 'package:flutter/foundation.dart';
import 'package:immich_mobile/domain/entities/album.entity.dart';
import 'package:immich_mobile/domain/entities/asset.entity.dart';
import 'package:immich_mobile/domain/entities/log.entity.dart';
import 'package:immich_mobile/domain/entities/store.entity.dart';
import 'package:immich_mobile/domain/entities/user.entity.dart';
import 'package:immich_mobile/domain/interfaces/database.interface.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
@@ -14,7 +18,7 @@ import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';
import 'database.repository.drift.dart';
@DriftDatabase(tables: [Logs, Store, LocalAlbum, LocalAsset])
@DriftDatabase(tables: [Logs, Store, LocalAlbum, LocalAsset, User])
class DriftDatabaseRepository extends $DriftDatabaseRepository
implements IDatabaseRepository<GeneratedDatabase> {
DriftDatabaseRepository() : super(_openConnection());
@@ -51,6 +55,18 @@ class DriftDatabaseRepository extends $DriftDatabaseRepository
@override
// ignore: no-empty-block
void migrateDB() {
// No migrations yet
// Migrations are handled automatically using the migrator field
}
@override
MigrationStrategy get migration => MigrationStrategy(
onCreate: (m) => m.createAll(),
beforeOpen: (details) async {
if (kDebugMode) {
await validateDatabaseSchema();
}
},
// ignore: no-empty-block
onUpgrade: (m, from, to) async {},
);
}
@@ -1,3 +1,7 @@
import 'dart:async';
import 'package:drift/drift.dart';
import 'package:flutter/foundation.dart';
import 'package:immich_mobile/domain/entities/log.entity.drift.dart';
import 'package:immich_mobile/domain/interfaces/log.interface.dart';
import 'package:immich_mobile/domain/models/log.model.dart';
@@ -10,7 +14,7 @@ class LogDriftRepository implements ILogRepository {
@override
Future<List<LogMessage>> fetchLogs() async {
return await db.select(db.logs).map((l) => l.toModel()).get();
return await db.managers.logs.map((l) => l.toModel()).get();
}
@override
@@ -26,12 +30,65 @@ class LogDriftRepository implements ILogRepository {
}
});
}
@override
FutureOr<bool> add(LogMessage log) async {
try {
await db.transaction(() async {
await db.into(db.logs).insert(LogsCompanion.insert(
content: log.content,
level: log.level,
createdAt: Value(log.createdAt),
error: Value(log.error),
logger: Value(log.logger),
stack: Value(log.stack),
));
});
return true;
} catch (e) {
debugPrint("Error while adding a log to the DB - $e");
return false;
}
}
@override
FutureOr<bool> addAll(List<LogMessage> logs) async {
try {
await db.batch((b) {
b.insertAll(
db.logs,
logs.map((log) => LogsCompanion.insert(
content: log.content,
level: log.level,
createdAt: Value(log.createdAt),
error: Value(log.error),
logger: Value(log.logger),
stack: Value(log.stack),
)),
);
});
return true;
} catch (e) {
debugPrint("Error while adding a log to the DB - $e");
return false;
}
}
@override
FutureOr<bool> clear() async {
try {
await db.managers.logs.delete();
return true;
} catch (e) {
debugPrint("Error while clearning the logs in DB - $e");
return false;
}
}
}
extension _LogToLogMessage on Log {
LogMessage toModel() {
return LogMessage(
id: id,
content: content,
createdAt: createdAt,
level: level,
@@ -1,6 +1,5 @@
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/entities/store.entity.drift.dart';
import 'package:immich_mobile/domain/interfaces/store.interface.dart';
@@ -14,7 +13,7 @@ class StoreDriftRepository with LogContext implements IStoreRepository {
const StoreDriftRepository(this.db);
@override
FutureOr<T?> getValue<T, U>(StoreKey<T, U> key) async {
FutureOr<T?> tryGet<T, U>(StoreKey<T, U> key) async {
final storeData = await db.managers.store
.filter((s) => s.id.equals(key.id))
.getSingleOrNull();
@@ -22,7 +21,16 @@ class StoreDriftRepository with LogContext implements IStoreRepository {
}
@override
FutureOr<bool> setValue<T, U>(StoreKey<T, U> key, T value) async {
FutureOr<T> get<T, U>(StoreKey<T, U> key) async {
final value = await tryGet(key);
if (value == null) {
throw StoreKeyNotFoundException(key);
}
return value;
}
@override
FutureOr<bool> set<T, U>(StoreKey<T, U> key, T value) async {
try {
await db.transaction(() async {
final storeValue = key.converter.toPrimitive(value);
@@ -42,30 +50,18 @@ class StoreDriftRepository with LogContext implements IStoreRepository {
}
@override
FutureOr<void> deleteValue(StoreKey key) async {
FutureOr<void> delete(StoreKey key) async {
return await db.transaction(() async {
await db.managers.store.filter((s) => s.id.equals(key.id)).delete();
});
}
@override
Stream<List<StoreValue>> watchStore() {
return (db.select(db.store).map((s) {
final key = StoreKey.values.firstWhereOrNull((e) => e.id == s.id);
if (key != null) {
final value = _getValueFromStoreData(key, s);
return StoreValue(id: s.id, value: value);
}
return StoreValue(id: s.id, value: null);
})).watch();
}
@override
Stream<T?> watchValue<T, U>(StoreKey<T, U> key) {
Stream<T?> watch<T, U>(StoreKey<T, U> key) {
return db.managers.store
.filter((s) => s.id.equals(key.id))
.watchSingleOrNull()
.map((e) => _getValueFromStoreData(key, e));
.asyncMap((e) async => await _getValueFromStoreData(key, e));
}
@override
@@ -75,7 +71,10 @@ class StoreDriftRepository with LogContext implements IStoreRepository {
});
}
T? _getValueFromStoreData<T, U>(StoreKey<T, U> key, StoreData? data) {
FutureOr<T?> _getValueFromStoreData<T, U>(
StoreKey<T, U> key,
StoreData? data,
) async {
final primitive = switch (key.type) {
const (int) => data?.intValue,
const (String) => data?.stringValue,
@@ -0,0 +1,65 @@
import 'dart:async';
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/entities/user.entity.drift.dart';
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/repositories/database.repository.dart';
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
class UserDriftRepository with LogContext implements IUserRepository {
final DriftDatabaseRepository db;
const UserDriftRepository(this.db);
@override
FutureOr<User?> getUser(String userId) async {
return await db.managers.user
.filter((f) => f.id.equals(userId))
.map((u) => u.toModel())
.getSingleOrNull();
}
@override
FutureOr<bool> insertUser(User user) async {
try {
return await db.transaction(() async {
await db.into(db.user).insertOnConflictUpdate(UserCompanion.insert(
id: user.id,
name: user.name,
email: user.email,
profileImagePath: user.profileImagePath,
avatarColor: user.avatarColor,
inTimeline: Value(user.inTimeline),
isAdmin: Value(user.isAdmin),
memoryEnabled: Value(user.memoryEnabled),
quotaSizeInBytes: Value(user.quotaSizeInBytes),
quotaUsageInBytes: Value(user.quotaSizeInBytes),
updatedAt: Value(user.updatedAt),
));
return true;
});
} catch (e, s) {
log.severe("Cannot insert User into table - $user", e, s);
return false;
}
}
}
extension _UserDataToUser on UserData {
User toModel() {
return User(
id: id,
email: email,
avatarColor: avatarColor,
inTimeline: inTimeline,
isAdmin: isAdmin,
memoryEnabled: memoryEnabled,
name: name,
profileImagePath: profileImagePath,
quotaSizeInBytes: quotaSizeInBytes,
quotaUsageInBytes: quotaUsageInBytes,
updatedAt: updatedAt,
);
}
}