Skip to content

Commit 955541a

Browse files
authored
Breadcrumbs for database operations (#1656)
1 parent 2261c15 commit 955541a

14 files changed

+1163
-42
lines changed

.github/workflows/flutter_test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ jobs:
141141
run: |
142142
case "${{ matrix.target }}" in
143143
ios)
144-
device=$(xcrun simctl create sentryPhone com.apple.CoreSimulator.SimDeviceType.iPhone-14 com.apple.CoreSimulator.SimRuntime.iOS-16-4)
144+
device=$(xcrun simctl create sentryPhone com.apple.CoreSimulator.SimDeviceType.iPhone-14 com.apple.CoreSimulator.SimRuntime.iOS-17-0)
145145
xcrun simctl boot ${device}
146146
echo "platform=iOS Simulator,id=${device}" >> "$GITHUB_OUTPUT"
147147
;;

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Features
6+
7+
- Breadcrumbs for database operations ([#1656](https://github.com/getsentry/sentry-dart/pull/1656))
8+
39
## 7.12.0
410

511
### Enhancements

flutter/example/ios/Podfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,8 @@ end
4343
post_install do |installer|
4444
installer.pods_project.targets.each do |target|
4545
flutter_additional_ios_build_settings(target)
46+
target.build_configurations.each do |config|
47+
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
48+
end
4649
end
4750
end

sqflite/lib/src/sentry_batch.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ class SentryBatch implements Batch {
5656
span?.origin = SentryTraceOrigins.autoDbSqfliteBatch;
5757
setDatabaseAttributeData(span, _dbName);
5858

59+
var breadcrumb = Breadcrumb(
60+
message: _buffer.toString().trim(),
61+
data: {},
62+
type: 'query',
63+
);
64+
setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName);
65+
5966
try {
6067
final result = await _batch.apply(
6168
noResult: noResult,
@@ -64,14 +71,23 @@ class SentryBatch implements Batch {
6471

6572
span?.status = SpanStatus.ok();
6673

74+
breadcrumb.data?['status'] = 'ok';
75+
6776
return result;
6877
} catch (exception) {
6978
span?.throwable = exception;
7079
span?.status = SpanStatus.internalError();
7180

81+
breadcrumb.data?['status'] = 'internal_error';
82+
breadcrumb = breadcrumb.copyWith(
83+
level: SentryLevel.warning,
84+
);
85+
7286
rethrow;
7387
} finally {
7488
await span?.finish();
89+
// ignore: invalid_use_of_internal_member
90+
await _hub.scope.addBreadcrumb(breadcrumb);
7591
}
7692
});
7793
}
@@ -94,6 +110,13 @@ class SentryBatch implements Batch {
94110
span?.origin = SentryTraceOrigins.autoDbSqfliteBatch;
95111
setDatabaseAttributeData(span, _dbName);
96112

113+
var breadcrumb = Breadcrumb(
114+
message: _buffer.toString().trim(),
115+
data: {},
116+
type: 'query',
117+
);
118+
setDatabaseAttributeOnBreadcrumb(breadcrumb, _dbName);
119+
97120
try {
98121
final result = await _batch.commit(
99122
exclusive: exclusive,
@@ -102,15 +125,23 @@ class SentryBatch implements Batch {
102125
);
103126

104127
span?.status = SpanStatus.ok();
128+
breadcrumb.data?['status'] = 'ok';
105129

106130
return result;
107131
} catch (exception) {
108132
span?.throwable = exception;
109133
span?.status = SpanStatus.internalError();
110134

135+
breadcrumb.data?['status'] = 'internal_error';
136+
breadcrumb = breadcrumb.copyWith(
137+
level: SentryLevel.warning,
138+
);
139+
111140
rethrow;
112141
} finally {
113142
await span?.finish();
143+
// ignore: invalid_use_of_internal_member
144+
await _hub.scope.addBreadcrumb(breadcrumb);
114145
}
115146
});
116147
}

sqflite/lib/src/sentry_database.dart

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,24 +75,39 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database {
7575
Future<void> close() {
7676
return Future<void>(() async {
7777
final currentSpan = _hub.getSpan();
78+
final description = 'Close DB: ${_database.path}';
7879
final span = currentSpan?.startChild(
7980
dbOp,
80-
description: 'Close DB: ${_database.path}',
81+
description: description,
8182
);
8283
// ignore: invalid_use_of_internal_member
8384
span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase;
8485

86+
var breadcrumb = Breadcrumb(
87+
message: description,
88+
category: dbOp,
89+
data: {},
90+
type: 'query',
91+
);
92+
8593
try {
8694
await _database.close();
8795

8896
span?.status = SpanStatus.ok();
97+
breadcrumb.data?['status'] = 'ok';
8998
} catch (exception) {
9099
span?.throwable = exception;
91100
span?.status = SpanStatus.internalError();
101+
breadcrumb.data?['status'] = 'internal_error';
102+
breadcrumb = breadcrumb.copyWith(
103+
level: SentryLevel.warning,
104+
);
92105

93106
rethrow;
94107
} finally {
95108
await span?.finish();
109+
// ignore: invalid_use_of_internal_member
110+
await _hub.scope.addBreadcrumb(breadcrumb);
96111
}
97112
});
98113
}
@@ -126,14 +141,23 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database {
126141
}) {
127142
return Future<T>(() async {
128143
final currentSpan = _hub.getSpan();
144+
final description = 'Transaction DB: ${_database.path}';
129145
final span = currentSpan?.startChild(
130146
_dbSqlOp,
131-
description: 'Transaction DB: ${_database.path}',
147+
description: description,
132148
);
133149
// ignore: invalid_use_of_internal_member
134150
span?.origin = SentryTraceOrigins.autoDbSqfliteDatabase;
135151
setDatabaseAttributeData(span, dbName);
136152

153+
var breadcrumb = Breadcrumb(
154+
message: description,
155+
category: _dbSqlOp,
156+
data: {},
157+
type: 'query',
158+
);
159+
setDatabaseAttributeOnBreadcrumb(breadcrumb, dbName);
160+
137161
Future<T> newAction(Transaction txn) async {
138162
final executor = SentryDatabaseExecutor(
139163
txn,
@@ -152,15 +176,23 @@ class SentryDatabase extends SentryDatabaseExecutor implements Database {
152176
await _database.transaction(newAction, exclusive: exclusive);
153177

154178
span?.status = SpanStatus.ok();
179+
breadcrumb.data?['status'] = 'ok';
155180

156181
return result;
157182
} catch (exception) {
158183
span?.throwable = exception;
159184
span?.status = SpanStatus.internalError();
185+
breadcrumb.data?['status'] = 'internal_error';
186+
breadcrumb = breadcrumb.copyWith(
187+
level: SentryLevel.warning,
188+
);
160189

161190
rethrow;
162191
} finally {
163192
await span?.finish();
193+
194+
// ignore: invalid_use_of_internal_member
195+
await _hub.scope.addBreadcrumb(breadcrumb);
164196
}
165197
});
166198
}

0 commit comments

Comments
 (0)