From b096e84fd418c5f3564c12b49d11f32e46ca828b Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Tue, 7 Nov 2023 23:42:07 +0100 Subject: [PATCH] Add interceptor example to docs --- docs/lib/snippets/log_interceptor.dart | 92 ++++++++++++++++++++++++++ docs/pages/docs/Examples/tracing.md | 24 +++++++ docs/test/snippet_test.dart | 31 +++++++++ 3 files changed, 147 insertions(+) create mode 100644 docs/lib/snippets/log_interceptor.dart create mode 100644 docs/pages/docs/Examples/tracing.md diff --git a/docs/lib/snippets/log_interceptor.dart b/docs/lib/snippets/log_interceptor.dart new file mode 100644 index 00000000..979c8aa4 --- /dev/null +++ b/docs/lib/snippets/log_interceptor.dart @@ -0,0 +1,92 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:drift/drift.dart'; +import 'package:drift/native.dart'; + +// #docregion class +class LogInterceptor extends QueryInterceptor { + Future _run( + String description, FutureOr Function() operation) async { + final stopwatch = Stopwatch()..start(); + print('Running $description'); + + try { + final result = await operation(); + print(' => succeeded after ${stopwatch.elapsedMilliseconds}ms'); + return result; + } on Object catch (e) { + print(' => failed after ${stopwatch.elapsedMilliseconds}ms ($e)'); + rethrow; + } + } + + @override + TransactionExecutor beginTransaction(QueryExecutor parent) { + print('begin'); + return super.beginTransaction(parent); + } + + @override + Future commitTransaction(TransactionExecutor inner) { + return _run('commit', () => inner.send()); + } + + @override + Future rollbackTransaction(TransactionExecutor inner) { + return _run('rollback', () => inner.rollback()); + } + + @override + Future runBatched( + QueryExecutor executor, BatchedStatements statements) { + return _run( + 'batch with $statements', () => executor.runBatched(statements)); + } + + @override + Future runInsert( + QueryExecutor executor, String statement, List args) { + return _run( + '$statement with $args', () => executor.runInsert(statement, args)); + } + + @override + Future runUpdate( + QueryExecutor executor, String statement, List args) { + return _run( + '$statement with $args', () => executor.runUpdate(statement, args)); + } + + @override + Future runDelete( + QueryExecutor executor, String statement, List args) { + return _run( + '$statement with $args', () => executor.runDelete(statement, args)); + } + + @override + Future runCustom( + QueryExecutor executor, String statement, List args) { + return _run( + '$statement with $args', () => executor.runCustom(statement, args)); + } + + @override + Future>> runSelect( + QueryExecutor executor, String statement, List args) { + return _run( + '$statement with $args', () => executor.runSelect(statement, args)); + } +} +// #enddocregion class + +void use() { + final myDatabaseFile = File('/dev/null'); + + // #docregion use + NativeDatabase.createInBackground( + myDatabaseFile, + ).interceptWith(LogInterceptor()); + // #enddocregion use +} diff --git a/docs/pages/docs/Examples/tracing.md b/docs/pages/docs/Examples/tracing.md new file mode 100644 index 00000000..0d234a40 --- /dev/null +++ b/docs/pages/docs/Examples/tracing.md @@ -0,0 +1,24 @@ +--- +data: + title: "Tracing database operations" + description: Using the `QueryInterceptor` API to log details about database operations. +template: layouts/docs/single +--- + +{% assign snippets = 'package:drift_docs/snippets/log_interceptor.dart.excerpt.json' | readString | json_decode %} + +Drift provides the relatively simple `logStatements` option to print the statements it +executes. +The `QueryInterceptor` API can be used to extend this logging to provide more information, +which this example will show. + +{% include "blocks/snippet" snippets=snippets name="class" %} + +Interceptors can be applied with the `interceptWith` extension on `QueryExecutor` and +`DatabaseConnection`: + +{% include "blocks/snippet" snippets=snippets name="use" %} + +The `QueryInterceptor` class is pretty powerful, as it allows you to fully control the underlying +database connection. You could also use it to retry some failing statements or to aggregate +statistics about query times to an external monitoring service. diff --git a/docs/test/snippet_test.dart b/docs/test/snippet_test.dart index 16968961..e8b4f5bb 100644 --- a/docs/test/snippet_test.dart +++ b/docs/test/snippet_test.dart @@ -1,6 +1,7 @@ import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:drift_docs/snippets/dart_api/datetime_conversion.dart'; +import 'package:drift_docs/snippets/log_interceptor.dart'; import 'package:drift_docs/snippets/modular/schema_inspection.dart'; import 'package:test/test.dart'; @@ -117,4 +118,34 @@ void main() { expect(row.name, 'bar'); }); }); + + test('interceptor', () { + expect( + () async { + final db = + Database(NativeDatabase.memory().interceptWith(LogInterceptor())); + + await db.batch((batch) { + batch.insert(db.users, UsersCompanion.insert(name: 'foo')); + }); + + await db.users.all().get(); + }, + prints( + allOf( + stringContainsInOrder( + [ + 'begin', + 'Running batch with BatchedStatements', + ' => succeeded after ', + 'Running commit', + ' => succeeded after ', + 'Running SELECT * FROM "users"; with []', + ' => succeeded after' + ], + ), + ), + ), + ); + }); }