Skip to content

Commit

Permalink
draft impl
Browse files Browse the repository at this point in the history
  • Loading branch information
buenaflor committed Nov 2, 2023
1 parent 30c1193 commit eff8bd0
Show file tree
Hide file tree
Showing 17 changed files with 3,979 additions and 36 deletions.
1 change: 1 addition & 0 deletions dart/lib/src/sentry_trace_origins.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ class SentryTraceOrigins {
'auto.db.sqflite.database_executor';
static const autoDbSqfliteDatabaseFactory =
'auto.db.sqflite.database_factory';
static const autoDbDriftDatabaseExecutor = 'auto.db.drift.database.executor';
}
14 changes: 14 additions & 0 deletions drift/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Omit committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
1,596 changes: 1,596 additions & 0 deletions drift/CHANGELOG.md

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions drift/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2019 Sentry

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
33 changes: 33 additions & 0 deletions drift/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
include: package:lints/recommended.yaml

analyzer:
language:
strict-casts: true
strict-inference: true
strict-raw-types: true
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: error
# treat missing returns as a warning (not a hint)
missing_return: error
# allow having TODOs in the code
todo: ignore
# allow self-reference to deprecated members (we do this because otherwise we have
# to annotate every member in every test, assert, etc, when we deprecate something)
deprecated_member_use_from_same_package: warning
# ignore sentry/path on pubspec as we change it on deployment
invalid_dependency: ignore
unnecessary_import: ignore
exclude:
- example/**

linter:
rules:
- prefer_final_locals
- public_member_api_docs
- prefer_single_quotes
- prefer_relative_imports
- unnecessary_brace_in_string_interps
- implementation_imports
- require_trailing_commas
- unawaited_futures
3 changes: 3 additions & 0 deletions drift/dartdoc_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dartdoc:
errors:
- unresolved-doc-reference
1 change: 1 addition & 0 deletions drift/lib/sentry_drift.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
library sentry_drift;
155 changes: 155 additions & 0 deletions drift/lib/src/sentry_drift_database.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import 'dart:async';

import 'package:drift/backends.dart';
import 'package:meta/meta.dart';
import 'package:sentry/sentry.dart';
import 'sentry_span_helper.dart';

/// Signature of a function that opens a database connection when instructed to.
typedef DatabaseOpener = FutureOr<QueryExecutor> Function();

/// Sentry Drift Database Executor based on [LazyDatabase].
///
/// A special database executor that delegates work to another [QueryExecutor].
/// The other executor is lazily opened by a [DatabaseOpener].
class SentryDriftDatabase extends QueryExecutor {
final Hub _hub;
final _spanHelper = SentrySpanHelper(
// ignore: invalid_use_of_internal_member
SentryTraceOrigins.autoDbDriftDatabaseExecutor,
);

String? dbName = 'people-drift-impl';

@internal
// ignore: public_member_api_docs
static const dbNameKey = 'db.name';

@internal
// ignore: public_member_api_docs
static const dbOp = 'db';

@internal
// ignore: public_member_api_docs
static const dbSystemKey = 'db.system';

@internal
// ignore: public_member_api_docs
static const dbSystem = 'sqlite';

/// Underlying executor
late final QueryExecutor _delegate;

bool _delegateAvailable = false;
final SqlDialect _dialect;

Completer<void>? _openDelegate;

@override
SqlDialect get dialect {
// Drift reads dialect before database opened, so we must know in advance
if (_delegateAvailable && _dialect != _delegate.dialect) {
throw Exception('LazyDatabase created with $_dialect, but underlying '
'database is ${_delegate.dialect}.');
}
return _dialect;
}

/// The function that will open the database when this [SentryDriftDatabase] gets
/// opened for the first time.
final DatabaseOpener opener;

/// Declares a [SentryDriftDatabase] that will run [opener] when the database is
/// first requested to be opened. You must specify the same [dialect] as the
/// underlying database has
SentryDriftDatabase(
this.opener, {
SqlDialect dialect = SqlDialect.sqlite,
@internal Hub? hub,
}) : _dialect = dialect,
_hub = hub ?? HubAdapter() {
_spanHelper.setHub(_hub);
}

Future<void> _awaitOpened() {
if (_delegateAvailable) {
return Future.value();
} else if (_openDelegate != null) {
return _openDelegate!.future;
} else {
final delegate = _openDelegate = Completer();
Future.sync(opener).then((database) {
_delegate = database;
_delegateAvailable = true;
delegate.complete();
}, onError: delegate.completeError);
return delegate.future;
}
}

@override

@override
TransactionExecutor beginTransaction() {
final a = _delegate.beginTransaction();
print(a.toString());
return _delegate.beginTransaction();
}

@override
Future<bool> ensureOpen(QueryExecutorUser user) {
return _awaitOpened().then((_) => _delegate.ensureOpen(user));
}

@override
Future<void> runBatched(BatchedStatements statements) {
return _delegate.runBatched(statements);
}

@override
Future<void> runCustom(String statement, [List<Object?>? args]) {
return _spanHelper.asyncWrapInSpan('custom', () async {
return await _delegate.runCustom(statement, args);
}, dbName: dbName);
}

@override
Future<int> runDelete(String statement, List<Object?> args) {
return _spanHelper.asyncWrapInSpan('delete', () async {
return await _delegate.runDelete(statement, args);
}, dbName: dbName);
}

@override
Future<int> runInsert(String statement, List<Object?> args) {
return _spanHelper.asyncWrapInSpan('insert', () async {
return await _delegate.runInsert(statement, args);
}, dbName: dbName);
}

@override
Future<List<Map<String, Object?>>> runSelect(
String statement, List<Object?> args) {
return _spanHelper.asyncWrapInSpan('select', () async {
return await _delegate.runSelect(statement, args);
}, dbName: dbName);
}

@override
Future<int> runUpdate(String statement, List<Object?> args) {
return _spanHelper.asyncWrapInSpan('update', () async {
return await _delegate.runUpdate(statement, args);
}, dbName: dbName);
}

@override
Future<void> close() {
return _spanHelper.asyncWrapInSpan('close', () async {
if (_delegateAvailable) {
return _delegate.close();
} else {
return Future.value();
}
}, dbName: dbName);
}
}
60 changes: 60 additions & 0 deletions drift/lib/src/sentry_span_helper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import 'package:meta/meta.dart';

import 'package:sentry/sentry.dart';

import 'sentry_drift_database.dart';

/// @nodoc
@internal
class SentrySpanHelper {
/// @nodoc
Hub _hub = HubAdapter();

/// @nodoc
final String _origin;

/// @nodoc
SentrySpanHelper(this._origin);

/// @nodoc
void setHub(Hub hub) {
_hub = hub;
}

/// @nodoc
@internal
Future<T> asyncWrapInSpan<T>(
String description,
Future<T> Function() execute, {
String? dbName,
}) async {
final currentSpan = _hub.getSpan();
final span = currentSpan?.startChild(
SentryDriftDatabase.dbOp,
description: description,
);

// ignore: invalid_use_of_internal_member
span?.origin = _origin;

span?.setData(SentryDriftDatabase.dbSystemKey, SentryDriftDatabase.dbSystem);

if (dbName != null) {
span?.setData(SentryDriftDatabase.dbNameKey, dbName);
}

try {
final result = await execute();

span?.status = SpanStatus.ok();

return result;
} catch (exception) {
span?.throwable = exception;
span?.status = SpanStatus.internalError();
rethrow;
} finally {
await span?.finish();
}
}
}
27 changes: 27 additions & 0 deletions drift/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: sentry_drift
description: An integration which adds support for performance tracing for the drift package.
version: 7.12.0
homepage: https://docs.sentry.io/platforms/flutter/
repository: https://github.com/getsentry/sentry-dart
issue_tracker: https://github.com/getsentry/sentry-dart/issues

environment:
sdk: '>=2.17.0 <4.0.0'

dependencies:
sentry: 7.12.0
meta: ^1.3.0

drift: ^2.13.0
sqlite3_flutter_libs: ^0.5.0
path_provider: ^2.0.0
path: ^1.8.3

dev_dependencies:
lints: ^3.0.0
test: ^1.21.0
coverage: ^1.3.0
mockito: ^5.1.0
build_runner: ^2.4.6
drift_dev: ^2.13.0
yaml: ^3.1.0 # needed for version match (code and pubspec)
3 changes: 3 additions & 0 deletions drift/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependency_overrides:
sentry:
path: ../dart
11 changes: 11 additions & 0 deletions drift/test/mocks/mocks.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:mockito/annotations.dart';
import 'package:sentry/sentry.dart';

import '../test_database.dart';

@GenerateMocks([
Hub,
AppDatabase,
TodoItems,
])
void main() {}
Loading

0 comments on commit eff8bd0

Please sign in to comment.