logging framework

This commit is contained in:
austinried 2025-12-14 10:09:32 +09:00
parent 7f6ba4776a
commit 2837d4576e
8 changed files with 223 additions and 42 deletions

View File

@ -7,6 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../database/dao/sources_dao.dart'; import '../../database/dao/sources_dao.dart';
import '../../database/database.dart'; import '../../database/database.dart';
import '../../l10n/generated/app_localizations.dart'; import '../../l10n/generated/app_localizations.dart';
import '../../util/logger.dart';
import '../state/database.dart'; import '../state/database.dart';
import '../util/padding.dart'; import '../util/padding.dart';
@ -216,6 +217,7 @@ class _SettingsSourceScreen extends HookConsumerWidget {
} catch (e, _) { } catch (e, _) {
// showErrorSnackbar(context, e.toString()); // showErrorSnackbar(context, e.toString());
// log.severe('Saving source', e, st); // log.severe('Saving source', e, st);
logger.w('fuck');
error = true; error = true;
} finally { } finally {
isSaving.value = false; isSaving.value = false;

View File

@ -6,8 +6,7 @@ import '../../database/database.dart';
final databaseInitializer = FutureProvider<SubtracksDatabase>((ref) async { final databaseInitializer = FutureProvider<SubtracksDatabase>((ref) async {
final db = SubtracksDatabase(); final db = SubtracksDatabase();
await db await db.batch((batch) {
.batch((batch) {
batch.insertAll( batch.insertAll(
db.sources, db.sources,
[ [
@ -40,9 +39,6 @@ final databaseInitializer = FutureProvider<SubtracksDatabase>((ref) async {
useTokenAuth: Value(true), useTokenAuth: Value(true),
), ),
]); ]);
})
.onError((error, stack) {
print(error);
}); });
return db; return db;

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../util/logger.dart';
import '../state/source.dart'; import '../state/source.dart';
import '../util/color_scheme.dart'; import '../util/color_scheme.dart';
import 'theme.dart'; import 'theme.dart';
@ -36,8 +37,12 @@ class CoverArtTheme extends HookConsumerWidget {
: 'https://placehold.net/400x400.png', : 'https://placehold.net/400x400.png',
), ),
); );
} catch (err) { } catch (error, stackTrace) {
print(err); logger.w(
'Could not create color scheme from image provider',
error: error,
stackTrace: stackTrace,
);
return null; return null;
} }
}, },

View File

@ -7,6 +7,7 @@ import '../sources/models.dart' as models;
import 'converters.dart'; import 'converters.dart';
import 'dao/library_dao.dart'; import 'dao/library_dao.dart';
import 'dao/sources_dao.dart'; import 'dao/sources_dao.dart';
import 'log_interceptor.dart';
part 'database.g.dart'; part 'database.g.dart';
@ -27,14 +28,14 @@ class SubtracksDatabase extends _$SubtracksDatabase {
static QueryExecutor _openConnection() { static QueryExecutor _openConnection() {
return driftDatabase( return driftDatabase(
name: 'my_database', name: 'subtracks_database',
native: DriftNativeOptions( native: DriftNativeOptions(
databasePath: () async { databasePath: () async {
final directory = await getApplicationSupportDirectory(); final directory = await getApplicationSupportDirectory();
return path.join(directory.absolute.path, 'subtracks.sqlite'); return path.join(directory.absolute.path, 'subtracks.sqlite');
}, },
), ),
); ).interceptWith(LogInterceptor());
} }
@override @override

View File

@ -0,0 +1,120 @@
import 'dart:async';
import 'package:drift/drift.dart';
import 'package:logger/logger.dart';
import '../util/logger.dart';
/// https://drift.simonbinder.eu/examples/tracing/
class LogInterceptor extends QueryInterceptor {
Future<T> _run<T>(
String description,
FutureOr<T> Function() operation,
) async {
final trace = logger.level >= Level.trace;
final stopwatch = trace ? (Stopwatch()..start()) : null;
logger.t('Running $description');
try {
final result = await operation();
if (trace) {
logger.t(' => succeeded after ${stopwatch!.elapsedMilliseconds}ms');
}
return result;
} on Object catch (e, st) {
if (trace) {
logger.t(' => failed after ${stopwatch!.elapsedMilliseconds}ms');
}
logger.e('Query failed', error: e, stackTrace: st);
rethrow;
}
}
@override
TransactionExecutor beginTransaction(QueryExecutor parent) {
logger.t('begin');
return super.beginTransaction(parent);
}
@override
Future<void> commitTransaction(TransactionExecutor inner) {
return _run('commit', () => inner.send());
}
@override
Future<void> rollbackTransaction(TransactionExecutor inner) {
return _run('rollback', () => inner.rollback());
}
@override
Future<void> runBatched(
QueryExecutor executor,
BatchedStatements statements,
) {
return _run(
'batch with $statements',
() => executor.runBatched(statements),
);
}
@override
Future<int> runInsert(
QueryExecutor executor,
String statement,
List<Object?> args,
) {
return _run(
'$statement with $args',
() => executor.runInsert(statement, args),
);
}
@override
Future<int> runUpdate(
QueryExecutor executor,
String statement,
List<Object?> args,
) {
return _run(
'$statement with $args',
() => executor.runUpdate(statement, args),
);
}
@override
Future<int> runDelete(
QueryExecutor executor,
String statement,
List<Object?> args,
) {
return _run(
'$statement with $args',
() => executor.runDelete(statement, args),
);
}
@override
Future<void> runCustom(
QueryExecutor executor,
String statement,
List<Object?> args,
) {
return _run(
'$statement with $args',
() => executor.runCustom(statement, args),
);
}
@override
Future<List<Map<String, Object?>>> runSelect(
QueryExecutor executor,
String statement,
List<Object?> args,
) {
return _run(
'$statement with $args',
() => executor.runSelect(statement, args),
);
}
}

48
lib/util/logger.dart Normal file
View File

@ -0,0 +1,48 @@
import 'package:logger/logger.dart';
class LogLevelFilter extends LogFilter {
@override
bool shouldLog(LogEvent event) {
return event.level >= level!;
}
}
class SubtracksLogger extends Logger {
SubtracksLogger({
super.filter,
super.printer,
super.output,
required Level level,
}) : _level = level,
super(level: level);
final Level _level;
Level get level => _level;
}
SubtracksLogger createLogger() {
var isDebug = false;
assert(() {
isDebug = true;
return true;
}());
if (isDebug) {
return SubtracksLogger(
filter: DevelopmentFilter(),
printer: PrettyPrinter(),
output: ConsoleOutput(),
level: Level.debug,
);
}
// TODO: production logger
return SubtracksLogger(
filter: DevelopmentFilter(),
printer: PrettyPrinter(),
output: ConsoleOutput(),
level: Level.debug,
);
}
final logger = createLogger();

View File

@ -565,6 +565,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "6.0.0"
logger:
dependency: "direct main"
description:
name: logger
sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3
url: "https://pub.dev"
source: hosted
version: "2.6.2"
logging: logging:
dependency: transitive dependency: transitive
description: description:

View File

@ -26,6 +26,7 @@ dependencies:
infinite_scroll_pagination: ^5.1.1 infinite_scroll_pagination: ^5.1.1
intl: any intl: any
json_annotation: ^4.9.0 json_annotation: ^4.9.0
logger: ^2.6.2
material_color_utilities: ^0.11.1 material_color_utilities: ^0.11.1
material_symbols_icons: ^4.2874.0 material_symbols_icons: ^4.2874.0
octo_image: ^2.1.0 octo_image: ^2.1.0