mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 09:09:29 +01:00
logging framework
This commit is contained in:
parent
7f6ba4776a
commit
2837d4576e
@ -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;
|
||||||
|
|||||||
@ -6,44 +6,40 @@ 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,
|
[
|
||||||
[
|
SourcesCompanion.insert(
|
||||||
SourcesCompanion.insert(
|
id: Value(1),
|
||||||
id: Value(1),
|
name: 'test subsonic',
|
||||||
name: 'test subsonic',
|
isActive: Value(true),
|
||||||
isActive: Value(true),
|
),
|
||||||
),
|
SourcesCompanion.insert(
|
||||||
SourcesCompanion.insert(
|
id: Value(2),
|
||||||
id: Value(2),
|
name: 'test navidrome',
|
||||||
name: 'test navidrome',
|
isActive: Value(null),
|
||||||
isActive: Value(null),
|
),
|
||||||
),
|
],
|
||||||
],
|
mode: InsertMode.insertOrIgnore,
|
||||||
mode: InsertMode.insertOrIgnore,
|
);
|
||||||
);
|
batch.insertAllOnConflictUpdate(db.subsonicSettings, [
|
||||||
batch.insertAllOnConflictUpdate(db.subsonicSettings, [
|
SubsonicSettingsCompanion.insert(
|
||||||
SubsonicSettingsCompanion.insert(
|
sourceId: Value(1),
|
||||||
sourceId: Value(1),
|
address: Uri.parse('http://demo.subsonic.org'),
|
||||||
address: Uri.parse('http://demo.subsonic.org'),
|
username: 'guest1',
|
||||||
username: 'guest1',
|
password: 'guest',
|
||||||
password: 'guest',
|
useTokenAuth: Value(true),
|
||||||
useTokenAuth: Value(true),
|
),
|
||||||
),
|
SubsonicSettingsCompanion.insert(
|
||||||
SubsonicSettingsCompanion.insert(
|
sourceId: Value(2),
|
||||||
sourceId: Value(2),
|
address: Uri.parse('http://10.0.2.2:4533'),
|
||||||
address: Uri.parse('http://10.0.2.2:4533'),
|
username: 'admin',
|
||||||
username: 'admin',
|
password: 'password',
|
||||||
password: 'password',
|
useTokenAuth: Value(true),
|
||||||
useTokenAuth: Value(true),
|
),
|
||||||
),
|
]);
|
||||||
]);
|
});
|
||||||
})
|
|
||||||
.onError((error, stack) {
|
|
||||||
print(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
120
lib/database/log_interceptor.dart
Normal file
120
lib/database/log_interceptor.dart
Normal 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
48
lib/util/logger.dart
Normal 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();
|
||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user