From 347b8f41787fb94f35333cb740b7354f77ba7c5a Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 19 Sep 2023 16:58:23 +0200 Subject: [PATCH 01/20] Prepare breadcrumb tests --- sqflite/lib/src/sentry_batch.dart | 6 ++ sqflite/test/mocks/mocks.mocks.dart | 129 ++++++++++++++++++++-------- sqflite/test/sentry_batch_test.dart | 6 ++ 3 files changed, 105 insertions(+), 36 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index 150b1c51da..0c9179107b 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -72,6 +72,9 @@ class SentryBatch implements Batch { rethrow; } finally { await span?.finish(); + await _hub.scope.addBreadcrumb( + Breadcrumb(), + ); } }); } @@ -111,6 +114,9 @@ class SentryBatch implements Batch { rethrow; } finally { await span?.finish(); + await _hub.scope.addBreadcrumb( + Breadcrumb(), + ); } }); } diff --git a/sqflite/test/mocks/mocks.mocks.dart b/sqflite/test/mocks/mocks.mocks.dart index 582663e5f9..6c4c5e362e 100644 --- a/sqflite/test/mocks/mocks.mocks.dart +++ b/sqflite/test/mocks/mocks.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.0 from annotations +// Mocks generated by Mockito 5.4.2 from annotations // in sentry_sqflite/test/mocks/mocks.dart. // Do not manually edit this file. @@ -6,12 +6,13 @@ import 'dart:async' as _i4; import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i7; import 'package:sentry/sentry.dart' as _i2; import 'package:sentry/src/sentry_tracer.dart' as _i5; import 'package:sqflite_common/sql.dart' as _i6; import 'package:sqflite_common/sqlite_api.dart' as _i3; -import 'mocks.dart' as _i7; +import 'mocks.dart' as _i8; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -76,7 +77,7 @@ class _FakeDatabase_4 extends _i1.SmartFake implements _i3.Database { ); } -class _FakeFuture_5 extends _i1.SmartFake implements _i4.Future { +class _FakeFuture_5 extends _i1.SmartFake implements _i4.Future { _FakeFuture_5( Object parent, Invocation parentInvocation, @@ -126,8 +127,18 @@ class _FakeSentryId_9 extends _i1.SmartFake implements _i2.SentryId { ); } -class _FakeHub_10 extends _i1.SmartFake implements _i2.Hub { - _FakeHub_10( +class _FakeScope_10 extends _i1.SmartFake implements _i2.Scope { + _FakeScope_10( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeHub_11 extends _i1.SmartFake implements _i2.Hub { + _FakeHub_11( Object parent, Invocation parentInvocation, ) : super( @@ -666,14 +677,25 @@ class MockDatabase extends _i1.Mock implements _i3.Database { [action], {#exclusive: exclusive}, ), - returnValue: _FakeFuture_5( - this, - Invocation.method( - #transaction, - [action], - {#exclusive: exclusive}, - ), - ), + returnValue: _i7.ifNotNull( + _i7.dummyValueOrNull( + this, + Invocation.method( + #transaction, + [action], + {#exclusive: exclusive}, + ), + ), + (T v) => _i4.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method( + #transaction, + [action], + {#exclusive: exclusive}, + ), + ), ) as _i4.Future); @override _i4.Future devInvokeMethod( @@ -688,16 +710,29 @@ class MockDatabase extends _i1.Mock implements _i3.Database { arguments, ], ), - returnValue: _FakeFuture_5( - this, - Invocation.method( - #devInvokeMethod, - [ - method, - arguments, - ], - ), - ), + returnValue: _i7.ifNotNull( + _i7.dummyValueOrNull( + this, + Invocation.method( + #devInvokeMethod, + [ + method, + arguments, + ], + ), + ), + (T v) => _i4.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method( + #devInvokeMethod, + [ + method, + arguments, + ], + ), + ), ) as _i4.Future); @override _i4.Future devInvokeSqlMethod( @@ -714,17 +749,31 @@ class MockDatabase extends _i1.Mock implements _i3.Database { arguments, ], ), - returnValue: _FakeFuture_5( - this, - Invocation.method( - #devInvokeSqlMethod, - [ - method, - sql, - arguments, - ], - ), - ), + returnValue: _i7.ifNotNull( + _i7.dummyValueOrNull( + this, + Invocation.method( + #devInvokeSqlMethod, + [ + method, + sql, + arguments, + ], + ), + ), + (T v) => _i4.Future.value(v), + ) ?? + _FakeFuture_5( + this, + Invocation.method( + #devInvokeSqlMethod, + [ + method, + sql, + arguments, + ], + ), + ), ) as _i4.Future); @override _i4.Future execute( @@ -1300,6 +1349,14 @@ class MockHub extends _i1.Mock implements _i2.Hub { ), ) as _i2.SentryId); @override + _i2.Scope get scope => (super.noSuchMethod( + Invocation.getter(#scope), + returnValue: _FakeScope_10( + this, + Invocation.getter(#scope), + ), + ) as _i2.Scope); + @override _i4.Future<_i2.SentryId> captureEvent( _i2.SentryEvent? event, { dynamic stackTrace, @@ -1433,7 +1490,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #clone, [], ), - returnValue: _FakeHub_10( + returnValue: _FakeHub_11( this, Invocation.method( #clone, @@ -1487,7 +1544,7 @@ class MockHub extends _i1.Mock implements _i2.Hub { #customSamplingContext: customSamplingContext, }, ), - returnValue: _i7.startTransactionShim( + returnValue: _i8.startTransactionShim( name, operation, description: description, diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index e3b24d811a..61298231ac 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -22,6 +22,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); // using ffi for testing on vm @@ -63,6 +64,9 @@ void main() { // ignore: invalid_use_of_internal_member expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb, isNotNull); + await db.close(); }); @@ -334,6 +338,7 @@ SELECT * FROM Product'''; fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); }); @@ -378,6 +383,7 @@ class Fixture { late final tracer = SentryTracer(_context, hub); final batch = MockBatch(); final exception = Exception('error'); + late final scope = Scope(options); Future getDatabase({ double? tracesSampleRate = 1.0, From 6de44bb8790ea6e54cc48ddbf0ef4cd183a83a99 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 25 Sep 2023 14:56:54 +0200 Subject: [PATCH 02/20] create breadcrumbs for batch operations --- sqflite/lib/src/sentry_batch.dart | 23 +- .../sentry_database_span_attributes.dart | 9 + sqflite/test/sentry_batch_test.dart | 274 +++++++++++++++++- 3 files changed, 301 insertions(+), 5 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index 0c9179107b..b137433863 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -56,6 +56,8 @@ class SentryBatch implements Batch { span?.origin = SentryTraceOrigins.autoDbSqfliteBatch; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _batch.apply( noResult: noResult, @@ -63,18 +65,23 @@ class SentryBatch implements Batch { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); - await _hub.scope.addBreadcrumb( - Breadcrumb(), + final breadcrumb = Breadcrumb( + message: _buffer.toString().trim(), + data: breadcrumbData, ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -97,6 +104,8 @@ class SentryBatch implements Batch { span?.origin = SentryTraceOrigins.autoDbSqfliteBatch; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _batch.commit( exclusive: exclusive, @@ -105,18 +114,24 @@ class SentryBatch implements Batch { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); - await _hub.scope.addBreadcrumb( - Breadcrumb(), + final breadcrumb = Breadcrumb( + message: _buffer.toString().trim(), + data: breadcrumbData, ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } diff --git a/sqflite/lib/src/utils/sentry_database_span_attributes.dart b/sqflite/lib/src/utils/sentry_database_span_attributes.dart index 119f2dd1b8..347c750ee8 100644 --- a/sqflite/lib/src/utils/sentry_database_span_attributes.dart +++ b/sqflite/lib/src/utils/sentry_database_span_attributes.dart @@ -10,3 +10,12 @@ void setDatabaseAttributeData(ISentrySpan? span, String? dbName) { span?.setData(SentryDatabase.dbNameKey, dbName); } } + +/// Sets the database attributes on the [breadcrumb]. +/// It contains the database system and the database name. +void setDatabaseAttributeOnBreadcrumb(Breadcrumb breadcrumb, String? dbName) { + breadcrumb.data?[SentryDatabase.dbSystemKey] = SentryDatabase.dbSystem; + if (dbName != null) { + breadcrumb.data?[SentryDatabase.dbNameKey] = dbName; + } +} diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index 61298231ac..688d9535be 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -65,7 +65,7 @@ void main() { expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb, isNotNull); + expect(breadcrumb.data?['status'], 'ok'); await db.close(); }); @@ -83,6 +83,9 @@ void main() { // ignore: invalid_use_of_internal_member expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'ok'); + await db.close(); }); @@ -106,6 +109,23 @@ void main() { await db.close(); }); + test('creates insert breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.insert('Product', {'title': 'Product 1'}); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'INSERT INTO Product (title) VALUES (?)', + ); + + await db.close(); + }); + test('creates raw insert span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -126,6 +146,23 @@ void main() { await db.close(); }); + test('creates raw insert breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.rawInsert('INSERT INTO Product (title) VALUES (?)', ['Product 1']); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'INSERT INTO Product (title) VALUES (?)', + ); + + await db.close(); + }); + test('creates update span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -143,6 +180,23 @@ void main() { await db.close(); }); + test('creates update breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.update('Product', {'title': 'Product 1'}); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'UPDATE Product SET title = ?', + ); + + await db.close(); + }); + test('creates raw update span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -160,6 +214,23 @@ void main() { await db.close(); }); + test('creates raw update breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.rawUpdate('UPDATE Product SET title = ?', ['Product 1']); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'UPDATE Product SET title = ?', + ); + + await db.close(); + }); + test('creates delete span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -177,6 +248,23 @@ void main() { await db.close(); }); + test('creates delete breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.delete('Product'); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'DELETE FROM Product', + ); + + await db.close(); + }); + test('creates raw delete span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -194,6 +282,23 @@ void main() { await db.close(); }); + test('creates raw delete breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.rawDelete('DELETE FROM Product'); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'DELETE FROM Product', + ); + + await db.close(); + }); + test('creates execute span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -211,6 +316,23 @@ void main() { await db.close(); }); + test('creates execute breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.execute('DELETE FROM Product'); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'DELETE FROM Product', + ); + + await db.close(); + }); + test('creates query span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -228,6 +350,23 @@ void main() { await db.close(); }); + test('creates query breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.query('Product'); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'SELECT * FROM Product', + ); + + await db.close(); + }); + test('creates raw query span', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -245,6 +384,23 @@ void main() { await db.close(); }); + test('creates raw query breadcrumb', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.rawQuery('SELECT * FROM Product'); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.message, + 'SELECT * FROM Product', + ); + + await db.close(); + }); + test('creates span with batch description', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -267,6 +423,24 @@ SELECT * FROM Product'''; await db.close(); }); + test('creates breadcrumb with batch description', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.insert('Product', {'title': 'Product 1'}); + batch.query('Product'); + + await batch.commit(); + + final desc = '''INSERT INTO Product (title) VALUES (?) +SELECT * FROM Product'''; + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.message, desc); + + await db.close(); + }); + test('creates span with batch description using apply', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -289,6 +463,24 @@ SELECT * FROM Product'''; await db.close(); }); + test('creates breadcrumb with batch description using apply', () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.insert('Product', {'title': 'Product 1'}); + batch.query('Product'); + + await batch.apply(); + + final desc = '''INSERT INTO Product (title) VALUES (?) +SELECT * FROM Product'''; + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.message, desc); + + await db.close(); + }); + test('apply creates db span with dbSystem and dbName attributes', () async { final db = await fixture.getDatabase(); final batch = db.batch(); @@ -304,6 +496,38 @@ SELECT * FROM Product'''; (db as SentryDatabase).dbName, ); + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect( + breadcrumb.data?[SentryDatabase.dbNameKey], + db.dbName, + ); + + await db.close(); + }); + + test('apply creates a breadcrumb with dbSystem and dbName attributes', + () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.insert('Product', {'title': 'Product 1'}); + + await batch.apply(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect( + breadcrumb.data?[SentryDatabase.dbNameKey], + (db as SentryDatabase).dbName, + ); + await db.close(); }); @@ -326,6 +550,28 @@ SELECT * FROM Product'''; await db.close(); }); + test('commit creates breadcrumb with dbSystem and dbName attributes', + () async { + final db = await fixture.getDatabase(); + final batch = db.batch(); + + batch.insert('Product', {'title': 'Product 1'}); + + await batch.commit(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect( + breadcrumb.data?[SentryDatabase.dbNameKey], + (db as SentryDatabase).dbName, + ); + + await db.close(); + }); + tearDown(() { databaseFactory = sqfliteDatabaseFactoryDefault; }); @@ -358,6 +604,19 @@ SELECT * FROM Product'''; expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); }); + test('commit sets batch to internal error if its thrown', () async { + final batch = SentryBatch(fixture.batch, hub: fixture.hub); + + when(fixture.batch.commit()).thenThrow(fixture.exception); + + batch.insert('Product', {'title': 'Product 1'}); + + await expectLater(() async => await batch.commit(), throwsException); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + test('apply sets span to internal error if its thrown', () async { final batch = SentryBatch(fixture.batch, hub: fixture.hub); @@ -373,6 +632,19 @@ SELECT * FROM Product'''; // ignore: invalid_use_of_internal_member expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); }); + + test('apply sets breadcrumb to internal error if its thrown', () async { + final batch = SentryBatch(fixture.batch, hub: fixture.hub); + + when(fixture.batch.apply()).thenThrow(fixture.exception); + + batch.insert('Product', {'title': 'Product 1'}); + + await expectLater(() async => await batch.apply(), throwsException); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); }); } From bd9a135476cbf85d46ee4dccd05b99da94c0d02e Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 25 Sep 2023 17:02:09 +0200 Subject: [PATCH 03/20] add breadcrumbs to sentry database & executor --- sqflite/lib/src/sentry_batch.dart | 1 + sqflite/lib/src/sentry_database.dart | 31 +- sqflite/lib/src/sentry_database_executor.dart | 143 ++++++ sqflite/test/sentry_database_test.dart | 420 ++++++++++++++++++ 4 files changed, 593 insertions(+), 2 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index b137433863..21d15ee108 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -81,6 +81,7 @@ class SentryBatch implements Batch { data: breadcrumbData, ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } }); diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index d148eb7ded..77bff544fc 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -75,24 +75,37 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { Future close() { return Future(() async { final currentSpan = _hub.getSpan(); + final description = 'Close DB: ${_database.path}'; final span = currentSpan?.startChild( dbOp, - description: 'Close DB: ${_database.path}', + description: description, ); // ignore: invalid_use_of_internal_member span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase; + final Map breadcrumbData = {}; + try { await _database.close(); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: description, + category: dbOp, + data: breadcrumbData, + ); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -126,14 +139,17 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { }) { return Future(() async { final currentSpan = _hub.getSpan(); + final description = 'Transaction DB: ${_database.path}'; final span = currentSpan?.startChild( _dbSqlOp, - description: 'Transaction DB: ${_database.path}', + description: description, ); // ignore: invalid_use_of_internal_member span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase; setDatabaseAttributeData(span, dbName); + final Map breadcrumbData = {}; + Future newAction(Transaction txn) async { final executor = SentryDatabaseExecutor( txn, @@ -152,15 +168,26 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { await _database.transaction(newAction, exclusive: exclusive); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: description, + category: _dbSqlOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index c232ca9e24..51b5682a6e 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -47,20 +47,33 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.delete(table, where: where, whereArgs: whereArgs); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -78,17 +91,30 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { await _executor.execute(sql, arguments); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -116,6 +142,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.insert( table, @@ -125,15 +153,26 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -173,6 +212,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.query( table, @@ -188,15 +229,26 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlQueryOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -237,6 +289,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.queryCursor( table, @@ -253,15 +307,26 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlQueryOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -278,19 +343,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.rawDelete(sql, arguments); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -307,19 +385,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.rawInsert(sql, arguments); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -339,19 +430,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.rawQuery(sql, arguments); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlQueryOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -372,6 +476,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.rawQueryCursor( sql, @@ -380,15 +486,26 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlQueryOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -405,19 +522,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.rawUpdate(sql, arguments); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } @@ -447,6 +577,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); + final Map breadcrumbData = {}; + try { final result = await _executor.update( table, @@ -457,15 +589,26 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlExecuteOp, + data: breadcrumbData, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index 5c954426bb..f24613c645 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -26,6 +26,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); // using ffi for testing on vm @@ -74,6 +75,16 @@ void main() { ); }); + test('creates close breadcrumb', () async { + final db = await fixture.getSut(); + + await db.close(); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.message, 'Close DB: $inMemoryDatabasePath'); + expect(breadcrumb.category, SentryDatabase.dbOp); + }); + test('creates transaction span', () async { final db = await fixture.getSut(); @@ -95,6 +106,26 @@ void main() { await db.close(); }); + test('creates transaction breadcrumb', () async { + final db = await fixture.getSut(); + + await db.transaction((txn) async { + expect(txn is SentrySqfliteTransaction, true); + }); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.message, 'Transaction DB: $inMemoryDatabasePath'); + expect(breadcrumb.category, 'db.sql.transaction'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates transaction children run by the transaction', () async { final db = await fixture.getSut(); @@ -177,6 +208,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); when(fixture.database.path).thenReturn('/path/db'); @@ -201,6 +233,17 @@ void main() { ); }); + test('close sets breadcrumb to internal error', () async { + when(fixture.database.close()).thenThrow(fixture.exception); + + final db = await fixture.getSut(database: fixture.database); + + await expectLater(() async => await db.close(), throwsException); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + test('transaction sets span to internal error', () async { // ignore: inference_failure_on_function_invocation when(fixture.database.transaction(any)).thenThrow(fixture.exception); @@ -222,6 +265,21 @@ void main() { SentryTraceOrigins.autoDbSqfliteDatabase, ); }); + + test('transaction sets breadcrumb to internal error', () async { + // ignore: inference_failure_on_function_invocation + when(fixture.database.transaction(any)).thenThrow(fixture.exception); + + final db = await fixture.getSut(database: fixture.database); + + await expectLater( + () async => await db.transaction((txn) async {}), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); }); group('$SentryDatabaseExecutor success', () { @@ -231,6 +289,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); // using ffi for testing on vm @@ -259,6 +318,24 @@ void main() { await db.close(); }); + test('creates delete breadcrumb', () async { + final db = await fixture.getSut(); + + await db.delete('Product'); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect(breadcrumb.message, 'DELETE FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates execute span', () async { final db = await fixture.getSut(); @@ -280,6 +357,24 @@ void main() { await db.close(); }); + test('creates execute span', () async { + final db = await fixture.getSut(); + + await db.execute('DELETE FROM Product'); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect(breadcrumb.message, 'DELETE FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates insert span', () async { final db = await fixture.getSut(); @@ -304,6 +399,27 @@ void main() { await db.close(); }); + test('creates insert breadcrumb', () async { + final db = await fixture.getSut(); + + await db.insert('Product', {'title': 'Product 1'}); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect( + breadcrumb.message, + 'INSERT INTO Product (title) VALUES (?)', + ); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates query span', () async { final db = await fixture.getSut(); @@ -325,6 +441,24 @@ void main() { await db.close(); }); + test('creates query breadcrumb', () async { + final db = await fixture.getSut(); + + await db.query('Product'); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.message, 'SELECT * FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates query cursor span', () async { final db = await fixture.getSut(); @@ -346,6 +480,24 @@ void main() { await db.close(); }); + test('creates query cursor breadcrumb', () async { + final db = await fixture.getSut(); + + await db.queryCursor('Product'); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.message, 'SELECT * FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates raw delete span', () async { final db = await fixture.getSut(); @@ -367,6 +519,24 @@ void main() { await db.close(); }); + test('creates raw delete breadcrumb', () async { + final db = await fixture.getSut(); + + await db.rawDelete('DELETE FROM Product'); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect(breadcrumb.message, 'DELETE FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates raw insert span', () async { final db = await fixture.getSut(); @@ -392,6 +562,25 @@ void main() { await db.close(); }); + test('creates raw insert breadcrumb', () async { + final db = await fixture.getSut(); + + await db + .rawInsert('INSERT INTO Product (title) VALUES (?)', ['Product 1']); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect(breadcrumb.message, 'INSERT INTO Product (title) VALUES (?)'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates raw query span', () async { final db = await fixture.getSut(); @@ -413,6 +602,24 @@ void main() { await db.close(); }); + test('creates raw query breadcrumb', () async { + final db = await fixture.getSut(); + + await db.rawQuery('SELECT * FROM Product'); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.message, 'SELECT * FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates raw query cursor span', () async { final db = await fixture.getSut(); @@ -434,6 +641,24 @@ void main() { await db.close(); }); + test('creates raw query cursor breadcrumb', () async { + final db = await fixture.getSut(); + + await db.rawQueryCursor('SELECT * FROM Product', []); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.message, 'SELECT * FROM Product'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates raw update span', () async { final db = await fixture.getSut(); @@ -455,6 +680,24 @@ void main() { await db.close(); }); + test('creates raw update breadcrumb', () async { + final db = await fixture.getSut(); + + await db.rawUpdate('UPDATE Product SET title = ?', ['Product 1']); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect(breadcrumb.message, 'UPDATE Product SET title = ?'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + test('creates update span', () async { final db = await fixture.getSut(); @@ -476,6 +719,24 @@ void main() { await db.close(); }); + test('creates update breadcrumb', () async { + final db = await fixture.getSut(); + + await db.update('Product', {'title': 'Product 1'}); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db.sql.execute'); + expect(breadcrumb.message, 'UPDATE Product SET title = ?'); + expect(breadcrumb.data?['status'], 'ok'); + expect( + breadcrumb.data?[SentryDatabase.dbSystemKey], + SentryDatabase.dbSystem, + ); + expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + + await db.close(); + }); + tearDown(() { databaseFactory = sqfliteDatabaseFactoryDefault; }); @@ -488,6 +749,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); }); @@ -724,6 +986,163 @@ void main() { SentryTraceOrigins.autoDbSqfliteDatabaseExecutor, ); }); + + test('delete sets breadcrumb to internal error', () async { + when(fixture.executor.delete(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.delete('Product'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('execute sets breadcrumb to internal error', () async { + when(fixture.executor.execute(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.execute('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('insert sets breadcrumb to internal error', () async { + when(fixture.executor.insert(any, any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor + .insert('Product', {'title': 'Product 1'}), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('query sets breadcrumb to internal error', () async { + when(fixture.executor.query(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.query('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('query cursor sets breadcrumb to internal error', () async { + when(fixture.executor.queryCursor(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.queryCursor('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('raw delete sets breadcrumb to internal error', () async { + when(fixture.executor.rawDelete(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.rawDelete('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('raw insert sets breadcrumb to internal error', () async { + when(fixture.executor.rawInsert(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.rawInsert('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('raw query sets breadcrumb to internal error', () async { + when(fixture.executor.rawQuery(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.rawQuery('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('raw query cursor sets breadcrumb to internal error', () async { + when(fixture.executor.rawQueryCursor(any, any)) + .thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.rawQueryCursor('sql', []), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('raw update sets breadcrumb to internal error', () async { + when(fixture.executor.rawUpdate(any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor.rawUpdate('sql'), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); + + test('update sets breadcrumb to internal error', () async { + when(fixture.executor.update(any, any)).thenThrow(fixture.exception); + + final executor = fixture.getExecutorSut(); + + await expectLater( + () async => await executor + .update('Product', {'title': 'Product 1'}), + throwsException, + ); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.data?['status'], 'internalError'); + }); }); } @@ -735,6 +1154,7 @@ class Fixture { final database = MockDatabase(); final exception = Exception('error'); final executor = MockDatabaseExecutor(); + late final scope = Scope(options); Future getSut({ double? tracesSampleRate = 1.0, From 2e6d025c78947fce4601a48ffa64b806a5e58184 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 25 Sep 2023 17:10:38 +0200 Subject: [PATCH 04/20] create breadcrumb when opening db --- sqflite/lib/src/sentry_sqflite.dart | 16 +++++++++++++++- sqflite/test/sentry_sqflite_test.dart | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/sqflite/lib/src/sentry_sqflite.dart b/sqflite/lib/src/sentry_sqflite.dart index ebd39b547b..e4bd5de573 100644 --- a/sqflite/lib/src/sentry_sqflite.dart +++ b/sqflite/lib/src/sentry_sqflite.dart @@ -40,13 +40,16 @@ Future openDatabaseWithSentry( final newHub = hub ?? HubAdapter(); final currentSpan = newHub.getSpan(); + final description = 'Open DB: $path'; final span = currentSpan?.startChild( SentryDatabase.dbOp, - description: 'Open DB: $path', + description: description, ); // ignore: invalid_use_of_internal_member span?.origin = SentryTraceOrigins.autoDbSqfliteOpenDatabase; + final Map breadcrumbData = {}; + try { final database = await databaseFactory.openDatabase(path, options: dbOptions); @@ -54,14 +57,25 @@ Future openDatabaseWithSentry( final sentryDatabase = SentryDatabase(database, hub: newHub); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; + return sentryDatabase; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: description, + category: SentryDatabase.dbOp, + data: breadcrumbData, + ); + // ignore: invalid_use_of_internal_member + await newHub.scope.addBreadcrumb(breadcrumb); } }); } diff --git a/sqflite/test/sentry_sqflite_test.dart b/sqflite/test/sentry_sqflite_test.dart index ff75d67e6d..27851881b0 100644 --- a/sqflite/test/sentry_sqflite_test.dart +++ b/sqflite/test/sentry_sqflite_test.dart @@ -24,6 +24,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); // using ffi for testing on vm @@ -68,6 +69,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); // using ffi for testing on vm @@ -101,6 +103,18 @@ void main() { await db.close(); }); + + test('creates db open breadcrumb', () async { + final db = + await openDatabaseWithSentry(inMemoryDatabasePath, hub: fixture.hub); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, SentryDatabase.dbOp); + expect(breadcrumb.message, 'Open DB: $inMemoryDatabasePath'); + expect(breadcrumb.data?['status'], 'ok'); + + await db.close(); + }); }); } @@ -109,4 +123,5 @@ class Fixture { final options = SentryOptions(dsn: fakeDsn)..tracesSampleRate = 1.0; final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); + late final scope = Scope(options); } From b7a2fbcd724a26af7b4fe90766a5a1a86e0a5cdb Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 25 Sep 2023 17:18:18 +0200 Subject: [PATCH 05/20] create breadcrumb in SentrySqfliteDatabaseFactory --- .../lib/src/sentry_sqflite_database_factory.dart | 16 +++++++++++++++- ...entry_sqflite_database_factory_dart_test.dart | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/sqflite/lib/src/sentry_sqflite_database_factory.dart b/sqflite/lib/src/sentry_sqflite_database_factory.dart index 4fff7479b1..ed5b06beea 100644 --- a/sqflite/lib/src/sentry_sqflite_database_factory.dart +++ b/sqflite/lib/src/sentry_sqflite_database_factory.dart @@ -59,15 +59,18 @@ class SentrySqfliteDatabaseFactory with SqfliteDatabaseFactoryMixin { return Future(() async { final currentSpan = _hub.getSpan(); + final description = 'Open DB: $path'; final span = currentSpan?.startChild( SentryDatabase.dbOp, - description: 'Open DB: $path', + description: description, ); span?.origin = // ignore: invalid_use_of_internal_member SentryTraceOrigins.autoDbSqfliteDatabaseFactory; + final Map breadcrumbData = {}; + try { final database = await databaseFactory.openDatabase(path, options: options); @@ -75,14 +78,25 @@ class SentrySqfliteDatabaseFactory with SqfliteDatabaseFactoryMixin { final sentryDatabase = SentryDatabase(database, hub: _hub); span?.status = SpanStatus.ok(); + breadcrumbData['status'] = 'ok'; + return sentryDatabase; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); + breadcrumbData['status'] = 'internalError'; rethrow; } finally { await span?.finish(); + + final breadcrumb = Breadcrumb( + message: description, + category: SentryDatabase.dbOp, + data: breadcrumbData, + ); + // ignore: invalid_use_of_internal_member + await _hub.scope.addBreadcrumb(breadcrumb); } }); } diff --git a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart index d2ed2e9fb5..9f2323165a 100644 --- a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart +++ b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart @@ -24,6 +24,7 @@ void main() { fixture = Fixture(); when(fixture.hub.options).thenReturn(fixture.options); + when(fixture.hub.scope).thenReturn(fixture.scope); when(fixture.hub.getSpan()).thenReturn(fixture.tracer); // using ffi for testing on vm @@ -70,6 +71,19 @@ void main() { ); await db.close(); }); + + test('starts and finishes a open db breadcrumb when performance enabled', () async { + final db = await openDatabase(inMemoryDatabasePath); + + expect((db as SentryDatabase).dbName, inMemoryDatabasePath); + + final breadcrumb = fixture.hub.scope.breadcrumbs.first; + expect(breadcrumb.category, 'db'); + expect(breadcrumb.message, 'Open DB: $inMemoryDatabasePath'); + expect(breadcrumb.data?['status'], 'ok'); + + await db.close(); + }); }); tearDown(() { @@ -82,4 +96,5 @@ class Fixture { final options = SentryOptions(dsn: fakeDsn)..tracesSampleRate = 1.0; final _context = SentryTransactionContext('name', 'operation'); late final tracer = SentryTracer(_context, hub); + late final scope = Scope(options); } From 86d796e10d39b03aede2e366c33b81b1414ec0c4 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 10:55:41 +0200 Subject: [PATCH 06/20] choose correct breadcrumb in batch tests --- sqflite/test/sentry_batch_test.dart | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index 688d9535be..9a944e4954 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -64,7 +64,7 @@ void main() { // ignore: invalid_use_of_internal_member expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'ok'); await db.close(); @@ -83,7 +83,7 @@ void main() { // ignore: invalid_use_of_internal_member expect(span.origin, SentryTraceOrigins.autoDbSqfliteBatch); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'ok'); await db.close(); @@ -117,7 +117,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'INSERT INTO Product (title) VALUES (?)', @@ -154,7 +154,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'INSERT INTO Product (title) VALUES (?)', @@ -188,7 +188,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'UPDATE Product SET title = ?', @@ -222,7 +222,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'UPDATE Product SET title = ?', @@ -256,7 +256,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'DELETE FROM Product', @@ -290,7 +290,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'DELETE FROM Product', @@ -324,7 +324,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'DELETE FROM Product', @@ -358,7 +358,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'SELECT * FROM Product', @@ -392,7 +392,7 @@ void main() { await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.message, 'SELECT * FROM Product', @@ -435,7 +435,7 @@ SELECT * FROM Product'''; final desc = '''INSERT INTO Product (title) VALUES (?) SELECT * FROM Product'''; - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.message, desc); await db.close(); @@ -475,7 +475,7 @@ SELECT * FROM Product'''; final desc = '''INSERT INTO Product (title) VALUES (?) SELECT * FROM Product'''; - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.message, desc); await db.close(); @@ -496,7 +496,7 @@ SELECT * FROM Product'''; (db as SentryDatabase).dbName, ); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.data?[SentryDatabase.dbSystemKey], SentryDatabase.dbSystem, @@ -518,7 +518,7 @@ SELECT * FROM Product'''; await batch.apply(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.data?[SentryDatabase.dbSystemKey], SentryDatabase.dbSystem, @@ -559,7 +559,7 @@ SELECT * FROM Product'''; await batch.commit(); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect( breadcrumb.data?[SentryDatabase.dbSystemKey], SentryDatabase.dbSystem, @@ -613,7 +613,7 @@ SELECT * FROM Product'''; await expectLater(() async => await batch.commit(), throwsException); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'internalError'); }); @@ -642,7 +642,7 @@ SELECT * FROM Product'''; await expectLater(() async => await batch.apply(), throwsException); - final breadcrumb = fixture.hub.scope.breadcrumbs.first; + final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'internalError'); }); }); From cfc7715a97f1d43fd16f99a79f5df6c898f70d7a Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 11:02:39 +0200 Subject: [PATCH 07/20] set additional error info in batch --- sqflite/lib/src/sentry_batch.dart | 41 ++++++++++++++++++----------- sqflite/test/sentry_batch_test.dart | 4 +++ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index 21d15ee108..28b5dccfd1 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -56,7 +56,11 @@ class SentryBatch implements Batch { span?.origin = SentryTraceOrigins.autoDbSqfliteBatch; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: _buffer.toString().trim(), + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _batch.apply( @@ -65,22 +69,23 @@ class SentryBatch implements Batch { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - final breadcrumb = Breadcrumb( - message: _buffer.toString().trim(), - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -105,7 +110,11 @@ class SentryBatch implements Batch { span?.origin = SentryTraceOrigins.autoDbSqfliteBatch; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: _buffer.toString().trim(), + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _batch.commit( @@ -115,22 +124,22 @@ class SentryBatch implements Batch { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - final breadcrumb = Breadcrumb( - message: _buffer.toString().trim(), - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index 9a944e4954..b17544f499 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -615,6 +615,8 @@ SELECT * FROM Product'''; final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('apply sets span to internal error if its thrown', () async { @@ -644,6 +646,8 @@ SELECT * FROM Product'''; final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); }); } From 98ee0af464810ab29142b152f62878a960894711 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 11:21:29 +0200 Subject: [PATCH 08/20] set query and error breadcrumb type --- sqflite/lib/src/sentry_database.dart | 42 +-- sqflite/lib/src/sentry_database_executor.dart | 250 ++++++++++-------- sqflite/test/sentry_database_test.dart | 30 +++ 3 files changed, 194 insertions(+), 128 deletions(-) diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index 77bff544fc..cfc3e87fc0 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -83,27 +83,29 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { // ignore: invalid_use_of_internal_member span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase; - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: description, + category: dbOp, + data: {}, + ); try { await _database.close(); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: description, - category: dbOp, - data: breadcrumbData, - ); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -148,7 +150,12 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase; setDatabaseAttributeData(span, dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: description, + category: _dbSqlOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, dbName); Future newAction(Transaction txn) async { final executor = SentryDatabaseExecutor( @@ -168,24 +175,23 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { await _database.transaction(newAction, exclusive: exclusive); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - final breadcrumb = Breadcrumb( - message: description, - category: _dbSqlOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, dbName); + // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index 51b5682a6e..c189530950 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -47,31 +47,33 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.delete(table, where: where, whereArgs: whereArgs); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: builder.sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -91,28 +93,34 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { await _executor.execute(sql, arguments); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -142,7 +150,12 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.insert( @@ -153,24 +166,21 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: builder.sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -212,7 +222,13 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlQueryOp, + data: {}, + type: 'query', + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.query( @@ -229,24 +245,21 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: builder.sql, - category: SentryDatabase.dbSqlQueryOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -289,7 +302,13 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlQueryOp, + data: {}, + type: 'query', + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.queryCursor( @@ -307,24 +326,21 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: builder.sql, - category: SentryDatabase.dbSqlQueryOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -343,30 +359,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.rawDelete(sql, arguments); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -385,30 +403,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.rawInsert(sql, arguments); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -430,30 +450,33 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlQueryOp, + data: {}, + type: 'query', + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.rawQuery(sql, arguments); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlQueryOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -476,7 +499,13 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlQueryOp, + data: {}, + type: 'query', + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.rawQueryCursor( @@ -486,24 +515,21 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlQueryOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -522,30 +548,32 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.rawUpdate(sql, arguments); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } @@ -577,7 +605,12 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.origin = SentryTraceOrigins.autoDbSqfliteDatabaseExecutor; setDatabaseAttributeData(span, _dbName); - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: builder.sql, + category: SentryDatabase.dbSqlExecuteOp, + data: {}, + ); + setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); try { final result = await _executor.update( @@ -589,24 +622,21 @@ class SentryDatabaseExecutor implements DatabaseExecutor { ); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return result; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: builder.sql, - category: SentryDatabase.dbSqlExecuteOp, - data: breadcrumbData, - ); - setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index f24613c645..1f3f29daa3 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -242,6 +242,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('transaction sets span to internal error', () async { @@ -279,6 +281,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); }); @@ -448,6 +452,7 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.type, 'query'); expect(breadcrumb.message, 'SELECT * FROM Product'); expect(breadcrumb.data?['status'], 'ok'); expect( @@ -487,6 +492,7 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.type, 'query'); expect(breadcrumb.message, 'SELECT * FROM Product'); expect(breadcrumb.data?['status'], 'ok'); expect( @@ -609,6 +615,7 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.type, 'query'); expect(breadcrumb.message, 'SELECT * FROM Product'); expect(breadcrumb.data?['status'], 'ok'); expect( @@ -648,6 +655,7 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.category, 'db.sql.query'); + expect(breadcrumb.type, 'query'); expect(breadcrumb.message, 'SELECT * FROM Product'); expect(breadcrumb.data?['status'], 'ok'); expect( @@ -999,6 +1007,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('execute sets breadcrumb to internal error', () async { @@ -1013,6 +1023,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('insert sets breadcrumb to internal error', () async { @@ -1028,6 +1040,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('query sets breadcrumb to internal error', () async { @@ -1042,6 +1056,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('query cursor sets breadcrumb to internal error', () async { @@ -1056,6 +1072,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('raw delete sets breadcrumb to internal error', () async { @@ -1070,6 +1088,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('raw insert sets breadcrumb to internal error', () async { @@ -1084,6 +1104,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('raw query sets breadcrumb to internal error', () async { @@ -1098,6 +1120,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('raw query cursor sets breadcrumb to internal error', () async { @@ -1113,6 +1137,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('raw update sets breadcrumb to internal error', () async { @@ -1127,6 +1153,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); test('update sets breadcrumb to internal error', () async { @@ -1142,6 +1170,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.type, 'error'); + expect(breadcrumb.level, SentryLevel.error); }); }); } From a38cfd564de6033299e7659041c0125516540c38 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 11:24:05 +0200 Subject: [PATCH 09/20] update in sqflite and database factory --- sqflite/lib/src/sentry_sqflite.dart | 20 ++++++++++-------- .../src/sentry_sqflite_database_factory.dart | 21 ++++++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/sqflite/lib/src/sentry_sqflite.dart b/sqflite/lib/src/sentry_sqflite.dart index e4bd5de573..cc8fd4ac38 100644 --- a/sqflite/lib/src/sentry_sqflite.dart +++ b/sqflite/lib/src/sentry_sqflite.dart @@ -48,7 +48,11 @@ Future openDatabaseWithSentry( // ignore: invalid_use_of_internal_member span?.origin = SentryTraceOrigins.autoDbSqfliteOpenDatabase; - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: description, + category: SentryDatabase.dbOp, + data: {}, + ); try { final database = @@ -57,23 +61,21 @@ Future openDatabaseWithSentry( final sentryDatabase = SentryDatabase(database, hub: newHub); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return sentryDatabase; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: description, - category: SentryDatabase.dbOp, - data: breadcrumbData, - ); // ignore: invalid_use_of_internal_member await newHub.scope.addBreadcrumb(breadcrumb); } diff --git a/sqflite/lib/src/sentry_sqflite_database_factory.dart b/sqflite/lib/src/sentry_sqflite_database_factory.dart index ed5b06beea..35bd28cec6 100644 --- a/sqflite/lib/src/sentry_sqflite_database_factory.dart +++ b/sqflite/lib/src/sentry_sqflite_database_factory.dart @@ -69,7 +69,11 @@ class SentrySqfliteDatabaseFactory with SqfliteDatabaseFactoryMixin { // ignore: invalid_use_of_internal_member SentryTraceOrigins.autoDbSqfliteDatabaseFactory; - final Map breadcrumbData = {}; + var breadcrumb = Breadcrumb( + message: description, + category: SentryDatabase.dbOp, + data: {}, + ); try { final database = @@ -78,23 +82,20 @@ class SentrySqfliteDatabaseFactory with SqfliteDatabaseFactoryMixin { final sentryDatabase = SentryDatabase(database, hub: _hub); span?.status = SpanStatus.ok(); - breadcrumbData['status'] = 'ok'; + breadcrumb.data?['status'] = 'ok'; return sentryDatabase; } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumbData['status'] = 'internalError'; - + breadcrumb.data?['status'] = 'internalError'; + breadcrumb = breadcrumb.copyWith( + type: 'error', + level: SentryLevel.error, + ); rethrow; } finally { await span?.finish(); - - final breadcrumb = Breadcrumb( - message: description, - category: SentryDatabase.dbOp, - data: breadcrumbData, - ); // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } From aa66f4a1b8d0358255db8e81a85f9e0ecd599e1f Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 11:26:01 +0200 Subject: [PATCH 10/20] run format --- sqflite/lib/src/sentry_database.dart | 3 +-- sqflite/lib/src/sentry_database_executor.dart | 8 ++++---- .../test/sentry_sqflite_database_factory_dart_test.dart | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index cfc3e87fc0..c1fcaf58e6 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -182,7 +182,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { span?.throwable = exception; span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internalError'; - breadcrumb = breadcrumb.copyWith( + breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, ); @@ -191,7 +191,6 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { } finally { await span?.finish(); - // ignore: invalid_use_of_internal_member await _hub.scope.addBreadcrumb(breadcrumb); } diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index c189530950..74301ef1bc 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -451,10 +451,10 @@ class SentryDatabaseExecutor implements DatabaseExecutor { setDatabaseAttributeData(span, _dbName); var breadcrumb = Breadcrumb( - message: sql, - category: SentryDatabase.dbSqlQueryOp, - data: {}, - type: 'query', + message: sql, + category: SentryDatabase.dbSqlQueryOp, + data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); diff --git a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart index 9f2323165a..9eeac66734 100644 --- a/sqflite/test/sentry_sqflite_database_factory_dart_test.dart +++ b/sqflite/test/sentry_sqflite_database_factory_dart_test.dart @@ -72,7 +72,8 @@ void main() { await db.close(); }); - test('starts and finishes a open db breadcrumb when performance enabled', () async { + test('starts and finishes a open db breadcrumb when performance enabled', + () async { final db = await openDatabase(inMemoryDatabasePath); expect((db as SentryDatabase).dbName, inMemoryDatabasePath); From 038238337f70a68cbb740ef840a7dc108e0a318f Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 13:30:19 +0200 Subject: [PATCH 11/20] add changelog entries --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40d3b04f3a..9277314364 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features - Breadcrumbs for file I/O operations ([#1649](https://github.com/getsentry/sentry-dart/pull/1649)) +- Breadcrumbs for database operations ([#1656](https://github.com/getsentry/sentry-dart/pull/1656)) ### Dependencies From 2778594b3e99ee4275927a649dd5959cc27d9f34 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Sep 2023 14:32:20 +0200 Subject: [PATCH 12/20] bump ios im runtime --- .github/workflows/flutter_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/flutter_test.yml b/.github/workflows/flutter_test.yml index 502efc1375..f3a4e80224 100644 --- a/.github/workflows/flutter_test.yml +++ b/.github/workflows/flutter_test.yml @@ -141,7 +141,7 @@ jobs: run: | case "${{ matrix.target }}" in ios) - device=$(xcrun simctl create sentryPhone com.apple.CoreSimulator.SimDeviceType.iPhone-14 com.apple.CoreSimulator.SimRuntime.iOS-16-4) + device=$(xcrun simctl create sentryPhone com.apple.CoreSimulator.SimDeviceType.iPhone-14 com.apple.CoreSimulator.SimRuntime.iOS-17-0) xcrun simctl boot ${device} echo "platform=iOS Simulator,id=${device}" >> "$GITHUB_OUTPUT" ;; From 9978a74120ef0b661fd7e74ec74b6f06feed78f0 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 3 Oct 2023 14:54:56 +0200 Subject: [PATCH 13/20] manually set deployemtn target for pods --- flutter/example/ios/Podfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flutter/example/ios/Podfile b/flutter/example/ios/Podfile index 7b1e6a2394..8d38fc9608 100644 --- a/flutter/example/ios/Podfile +++ b/flutter/example/ios/Podfile @@ -43,5 +43,8 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + end end end From 788364d24ff864883dfda29ee974a12aa74d33dc Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 17 Oct 2023 16:50:07 +0200 Subject: [PATCH 14/20] Change status value --- sqflite/lib/src/sentry_batch.dart | 4 +-- sqflite/lib/src/sentry_database.dart | 4 +-- sqflite/lib/src/sentry_database_executor.dart | 22 ++++++++-------- sqflite/lib/src/sentry_sqflite.dart | 2 +- .../src/sentry_sqflite_database_factory.dart | 2 +- sqflite/test/sentry_batch_test.dart | 4 +-- sqflite/test/sentry_database_test.dart | 26 +++++++++---------- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index 28b5dccfd1..cd8167be09 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -77,7 +77,7 @@ class SentryBatch implements Batch { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -131,7 +131,7 @@ class SentryBatch implements Batch { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index c1fcaf58e6..96af2aeba0 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -97,7 +97,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -181,7 +181,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index 74301ef1bc..91c4adfa6f 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -65,7 +65,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -108,7 +108,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -172,7 +172,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -251,7 +251,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -332,7 +332,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -376,7 +376,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -420,7 +420,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -468,7 +468,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -521,7 +521,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -565,7 +565,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, @@ -628,7 +628,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, diff --git a/sqflite/lib/src/sentry_sqflite.dart b/sqflite/lib/src/sentry_sqflite.dart index cc8fd4ac38..1adbdf8000 100644 --- a/sqflite/lib/src/sentry_sqflite.dart +++ b/sqflite/lib/src/sentry_sqflite.dart @@ -67,7 +67,7 @@ Future openDatabaseWithSentry( } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, diff --git a/sqflite/lib/src/sentry_sqflite_database_factory.dart b/sqflite/lib/src/sentry_sqflite_database_factory.dart index 35bd28cec6..70a377e533 100644 --- a/sqflite/lib/src/sentry_sqflite_database_factory.dart +++ b/sqflite/lib/src/sentry_sqflite_database_factory.dart @@ -88,7 +88,7 @@ class SentrySqfliteDatabaseFactory with SqfliteDatabaseFactoryMixin { } catch (exception) { span?.throwable = exception; span?.status = SpanStatus.internalError(); - breadcrumb.data?['status'] = 'internalError'; + breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( type: 'error', level: SentryLevel.error, diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index b17544f499..e1bfc03a15 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -614,7 +614,7 @@ SELECT * FROM Product'''; await expectLater(() async => await batch.commit(), throwsException); final breadcrumb = fixture.hub.scope.breadcrumbs.last; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -645,7 +645,7 @@ SELECT * FROM Product'''; await expectLater(() async => await batch.apply(), throwsException); final breadcrumb = fixture.hub.scope.breadcrumbs.last; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index 1f3f29daa3..8a5f602c4e 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -241,7 +241,7 @@ void main() { await expectLater(() async => await db.close(), throwsException); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -280,7 +280,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1006,7 +1006,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1022,7 +1022,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1039,7 +1039,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1055,7 +1055,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1071,7 +1071,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1087,7 +1087,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1103,7 +1103,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1119,7 +1119,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1136,7 +1136,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1152,7 +1152,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); @@ -1169,7 +1169,7 @@ void main() { ); final breadcrumb = fixture.hub.scope.breadcrumbs.first; - expect(breadcrumb.data?['status'], 'internalError'); + expect(breadcrumb.data?['status'], 'internal_error'); expect(breadcrumb.type, 'error'); expect(breadcrumb.level, SentryLevel.error); }); From af3d295d769b27916f338aca7e610d1b6a9afd70 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 24 Oct 2023 11:03:27 +0200 Subject: [PATCH 15/20] change breadcrumb type and level --- sqflite/lib/src/sentry_batch.dart | 8 +-- sqflite/lib/src/sentry_database.dart | 8 +-- sqflite/lib/src/sentry_database_executor.dart | 48 ++++++++--------- sqflite/test/sentry_batch_test.dart | 8 +-- sqflite/test/sentry_database_test.dart | 52 +++++++++---------- 5 files changed, 62 insertions(+), 62 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index cd8167be09..885259a67d 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -79,8 +79,8 @@ class SentryBatch implements Batch { breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -133,8 +133,8 @@ class SentryBatch implements Batch { breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index 96af2aeba0..56a94abdd8 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -99,8 +99,8 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -183,8 +183,8 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index 91c4adfa6f..a2592aee1c 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -67,8 +67,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -110,12 +110,12 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -174,8 +174,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -253,8 +253,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -334,8 +334,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -378,8 +378,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -422,8 +422,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -470,8 +470,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -523,8 +523,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -567,8 +567,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; @@ -630,8 +630,8 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + type: 'query', + level: SentryLevel.warning, ); rethrow; diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index e1bfc03a15..ff1fe4b27d 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -615,8 +615,8 @@ SELECT * FROM Product'''; final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('apply sets span to internal error if its thrown', () async { @@ -646,8 +646,8 @@ SELECT * FROM Product'''; final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); }); } diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index 8a5f602c4e..683422c3bc 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -242,8 +242,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('transaction sets span to internal error', () async { @@ -281,8 +281,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); }); @@ -1007,8 +1007,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('execute sets breadcrumb to internal error', () async { @@ -1023,8 +1023,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('insert sets breadcrumb to internal error', () async { @@ -1040,8 +1040,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('query sets breadcrumb to internal error', () async { @@ -1056,8 +1056,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('query cursor sets breadcrumb to internal error', () async { @@ -1072,8 +1072,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('raw delete sets breadcrumb to internal error', () async { @@ -1088,8 +1088,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('raw insert sets breadcrumb to internal error', () async { @@ -1104,8 +1104,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('raw query sets breadcrumb to internal error', () async { @@ -1120,8 +1120,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('raw query cursor sets breadcrumb to internal error', () async { @@ -1137,8 +1137,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('raw update sets breadcrumb to internal error', () async { @@ -1153,8 +1153,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); test('update sets breadcrumb to internal error', () async { @@ -1170,8 +1170,8 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.data?['status'], 'internal_error'); - expect(breadcrumb.type, 'error'); - expect(breadcrumb.level, SentryLevel.error); + expect(breadcrumb.type, 'query'); + expect(breadcrumb.level, SentryLevel.warning); }); }); } From 1a5d4e3ad7aecb8bfaa6b98e179a8dfad35812df Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 24 Oct 2023 11:18:40 +0200 Subject: [PATCH 16/20] remove duplicated lines --- sqflite/lib/src/sentry_database_executor.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index a2592aee1c..9848aedc17 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -113,10 +113,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { type: 'query', level: SentryLevel.warning, ); - breadcrumb = breadcrumb.copyWith( - type: 'query', - level: SentryLevel.warning, - ); rethrow; } finally { From aaf22b40ce002443659b6b87059af71e016225cd Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 24 Oct 2023 11:31:56 +0200 Subject: [PATCH 17/20] set type query to success breadcrumbs --- sqflite/lib/src/sentry_batch.dart | 4 ++-- sqflite/lib/src/sentry_database.dart | 4 ++-- sqflite/lib/src/sentry_database_executor.dart | 18 +++++++----------- sqflite/test/sentry_batch_test.dart | 13 +++++++++++++ sqflite/test/sentry_database_test.dart | 15 ++++++++++++++- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/sqflite/lib/src/sentry_batch.dart b/sqflite/lib/src/sentry_batch.dart index 885259a67d..a510ad186f 100644 --- a/sqflite/lib/src/sentry_batch.dart +++ b/sqflite/lib/src/sentry_batch.dart @@ -59,6 +59,7 @@ class SentryBatch implements Batch { var breadcrumb = Breadcrumb( message: _buffer.toString().trim(), data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -79,7 +80,6 @@ class SentryBatch implements Batch { breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -113,6 +113,7 @@ class SentryBatch implements Batch { var breadcrumb = Breadcrumb( message: _buffer.toString().trim(), data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -133,7 +134,6 @@ class SentryBatch implements Batch { breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); diff --git a/sqflite/lib/src/sentry_database.dart b/sqflite/lib/src/sentry_database.dart index 56a94abdd8..fafcad06d9 100644 --- a/sqflite/lib/src/sentry_database.dart +++ b/sqflite/lib/src/sentry_database.dart @@ -87,6 +87,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { message: description, category: dbOp, data: {}, + type: 'query', ); try { @@ -99,7 +100,6 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -154,6 +154,7 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { message: description, category: _dbSqlOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, dbName); @@ -183,7 +184,6 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); diff --git a/sqflite/lib/src/sentry_database_executor.dart b/sqflite/lib/src/sentry_database_executor.dart index 9848aedc17..f13b0eb261 100644 --- a/sqflite/lib/src/sentry_database_executor.dart +++ b/sqflite/lib/src/sentry_database_executor.dart @@ -51,6 +51,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: builder.sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -67,7 +68,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -97,6 +97,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -110,7 +111,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -150,6 +150,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: builder.sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -170,7 +171,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -249,7 +249,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -330,7 +329,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -359,6 +357,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -374,7 +373,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -403,6 +401,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -418,7 +417,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -466,7 +464,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -519,7 +516,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -548,6 +544,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -563,7 +560,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); @@ -605,6 +601,7 @@ class SentryDatabaseExecutor implements DatabaseExecutor { message: builder.sql, category: SentryDatabase.dbSqlExecuteOp, data: {}, + type: 'query', ); setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName); @@ -626,7 +623,6 @@ class SentryDatabaseExecutor implements DatabaseExecutor { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'query', level: SentryLevel.warning, ); diff --git a/sqflite/test/sentry_batch_test.dart b/sqflite/test/sentry_batch_test.dart index ff1fe4b27d..b9c53b8762 100644 --- a/sqflite/test/sentry_batch_test.dart +++ b/sqflite/test/sentry_batch_test.dart @@ -122,6 +122,7 @@ void main() { breadcrumb.message, 'INSERT INTO Product (title) VALUES (?)', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -159,6 +160,7 @@ void main() { breadcrumb.message, 'INSERT INTO Product (title) VALUES (?)', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -193,6 +195,7 @@ void main() { breadcrumb.message, 'UPDATE Product SET title = ?', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -227,6 +230,7 @@ void main() { breadcrumb.message, 'UPDATE Product SET title = ?', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -261,6 +265,7 @@ void main() { breadcrumb.message, 'DELETE FROM Product', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -295,6 +300,7 @@ void main() { breadcrumb.message, 'DELETE FROM Product', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -329,6 +335,7 @@ void main() { breadcrumb.message, 'DELETE FROM Product', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -363,6 +370,7 @@ void main() { breadcrumb.message, 'SELECT * FROM Product', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -397,6 +405,7 @@ void main() { breadcrumb.message, 'SELECT * FROM Product', ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -437,6 +446,7 @@ SELECT * FROM Product'''; final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.message, desc); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -477,6 +487,7 @@ SELECT * FROM Product'''; final breadcrumb = fixture.hub.scope.breadcrumbs.last; expect(breadcrumb.message, desc); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -527,6 +538,7 @@ SELECT * FROM Product'''; breadcrumb.data?[SentryDatabase.dbNameKey], (db as SentryDatabase).dbName, ); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -568,6 +580,7 @@ SELECT * FROM Product'''; breadcrumb.data?[SentryDatabase.dbNameKey], (db as SentryDatabase).dbName, ); + expect(breadcrumb.type, 'query'); await db.close(); }); diff --git a/sqflite/test/sentry_database_test.dart b/sqflite/test/sentry_database_test.dart index 683422c3bc..ad1a07b360 100644 --- a/sqflite/test/sentry_database_test.dart +++ b/sqflite/test/sentry_database_test.dart @@ -83,6 +83,7 @@ void main() { final breadcrumb = fixture.hub.scope.breadcrumbs.first; expect(breadcrumb.message, 'Close DB: $inMemoryDatabasePath'); expect(breadcrumb.category, SentryDatabase.dbOp); + expect(breadcrumb.type, 'query'); }); test('creates transaction span', () async { @@ -122,6 +123,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -336,6 +338,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -361,7 +364,7 @@ void main() { await db.close(); }); - test('creates execute span', () async { + test('creates execute breadcrumb', () async { final db = await fixture.getSut(); await db.execute('DELETE FROM Product'); @@ -375,6 +378,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -420,6 +424,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -460,6 +465,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -500,6 +506,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -539,6 +546,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -583,6 +591,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -623,6 +632,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -663,6 +673,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -702,6 +713,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); @@ -741,6 +753,7 @@ void main() { SentryDatabase.dbSystem, ); expect(breadcrumb.data?[SentryDatabase.dbNameKey], inMemoryDatabasePath); + expect(breadcrumb.type, 'query'); await db.close(); }); From 73d740a03ff8c5f524eeeefc4bec55f36061a9a4 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 30 Oct 2023 13:56:41 +0100 Subject: [PATCH 18/20] fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e53ef5e6cf..b5830d2b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Features - Initial (alpha) support for profiling on iOS and macOS ([#1611](https://github.com/getsentry/sentry-dart/pull/1611)) +- Breadcrumbs for database operations ([#1656](https://github.com/getsentry/sentry-dart/pull/1656)) ## 7.11.0 @@ -20,7 +21,6 @@ ### Features - Breadcrumbs for file I/O operations ([#1649](https://github.com/getsentry/sentry-dart/pull/1649)) -- Breadcrumbs for database operations ([#1656](https://github.com/getsentry/sentry-dart/pull/1656)) ### Dependencies From 2c353b223467ef4aaf806e5281ec9c8892c5d1fe Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 31 Oct 2023 16:43:57 +0100 Subject: [PATCH 19/20] remove remaining error level --- sqflite/lib/src/sentry_sqflite.dart | 3 +-- sqflite/lib/src/sentry_sqflite_database_factory.dart | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sqflite/lib/src/sentry_sqflite.dart b/sqflite/lib/src/sentry_sqflite.dart index 1adbdf8000..b26b767808 100644 --- a/sqflite/lib/src/sentry_sqflite.dart +++ b/sqflite/lib/src/sentry_sqflite.dart @@ -69,8 +69,7 @@ Future openDatabaseWithSentry( span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + level: SentryLevel.warning, ); rethrow; diff --git a/sqflite/lib/src/sentry_sqflite_database_factory.dart b/sqflite/lib/src/sentry_sqflite_database_factory.dart index 70a377e533..827e516afa 100644 --- a/sqflite/lib/src/sentry_sqflite_database_factory.dart +++ b/sqflite/lib/src/sentry_sqflite_database_factory.dart @@ -90,8 +90,7 @@ class SentrySqfliteDatabaseFactory with SqfliteDatabaseFactoryMixin { span?.status = SpanStatus.internalError(); breadcrumb.data?['status'] = 'internal_error'; breadcrumb = breadcrumb.copyWith( - type: 'error', - level: SentryLevel.error, + level: SentryLevel.warning, ); rethrow; } finally { From a20d1942028587a0243dd8a386c736335cb02d4f Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 31 Oct 2023 16:44:44 +0100 Subject: [PATCH 20/20] fix changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c38beb6b..5f24a7ed7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Breadcrumbs for database operations ([#1656](https://github.com/getsentry/sentry-dart/pull/1656)) + ## 7.12.0 ### Enhancements @@ -10,7 +16,6 @@ ### Features - Initial (alpha) support for profiling on iOS and macOS ([#1611](https://github.com/getsentry/sentry-dart/pull/1611)) -- Breadcrumbs for database operations ([#1656](https://github.com/getsentry/sentry-dart/pull/1656)) - Add `SentryNavigatorObserver` current route to `event.app.contexts.viewNames` ([#1545](https://github.com/getsentry/sentry-dart/pull/1545)) - Requires relay version [23.9.0](https://github.com/getsentry/relay/blob/master/CHANGELOG.md#2390) for self-hosted instances