Skip to content

Commit 3644f9a

Browse files
committed
feat: sentry error logging
1 parent b6a9cbb commit 3644f9a

File tree

5 files changed

+116
-40
lines changed

5 files changed

+116
-40
lines changed

lib/app/view/app.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class App extends StatelessWidget {
1919
required this.settingsBloc,
2020
super.key,
2121
});
22+
2223
final FlutterSecureStorage secureStorage;
2324
final SettingsBloc settingsBloc;
2425

lib/bootstrap.dart

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,73 @@ class AppBlocObserver extends BlocObserver {
2222

2323
@override
2424
void onError(BlocBase<dynamic> bloc, Object error, StackTrace stackTrace) {
25+
Sentry.captureException(
26+
error,
27+
stackTrace: stackTrace,
28+
);
29+
2530
log('onError(${bloc.runtimeType}, $error, $stackTrace)');
2631
super.onError(bloc, error, stackTrace);
2732
}
2833
}
2934

3035
Future<void> bootstrap(
36+
ISentrySpan span,
3137
FutureOr<Widget> Function(
3238
FlutterSecureStorage secureStorage,
3339
SettingsBloc settingsBloc,
3440
) builder,
3541
) async {
36-
SentryWidgetsFlutterBinding.ensureInitialized();
42+
final widgetFlutterBindingSpan = span.startChild(
43+
'initialize SentryWidgetsFlutterBinding',
44+
description: 'calls SentryWidgetsFlutterBinding.ensureInitialized()',
45+
);
46+
47+
// Ensure SentryWidgetsFlutterBinding is initialized
48+
try {
49+
SentryWidgetsFlutterBinding.ensureInitialized();
50+
} catch (e) {
51+
widgetFlutterBindingSpan
52+
..throwable = e
53+
..status = const SpanStatus.notFound();
54+
} finally {
55+
await widgetFlutterBindingSpan.finish();
56+
}
57+
3758
FlutterError.onError = (details) {
38-
// TODO: Add Sentry error reporting
39-
/*
4059
Sentry.captureException(
4160
details,
4261
stackTrace: details.stack,
4362
);
44-
*/
4563

4664
log(details.exceptionAsString(), stackTrace: details.stack);
4765
};
4866

4967
// Initialize local storage repository
5068
// final localStorage = LocalStorage(sharedPreferences);
5169

70+
final secureStorageBinding = span.startChild(
71+
'retrieve secure storage values',
72+
description: 'retrieve required startup values from secure storage',
73+
);
5274
// Initialize secure storage
5375
const secureStorage = FlutterSecureStorage();
54-
55-
// Create a random salt if it doesn't exist.
56-
final salt = await secureStorage.read(key: KeyNameConstants.md5Salt);
57-
if (salt == null || salt.isEmpty) {
58-
// Create a random salt and store it in secure storage
59-
await secureStorage.write(
60-
key: KeyNameConstants.md5Salt,
61-
value: DateTime.now().millisecondsSinceEpoch.toString(),
62-
);
76+
try {
77+
// Create a random salt if it doesn't exist.
78+
final salt = await secureStorage.read(key: KeyNameConstants.md5Salt);
79+
if (salt == null || salt.isEmpty) {
80+
// Create a random salt and store it in secure storage
81+
await secureStorage.write(
82+
key: KeyNameConstants.md5Salt,
83+
value: DateTime.now().millisecondsSinceEpoch.toString(),
84+
);
85+
}
86+
} catch (e) {
87+
secureStorageBinding
88+
..throwable = e
89+
..status = const SpanStatus.internalError();
90+
} finally {
91+
await secureStorageBinding.finish();
6392
}
6493

6594
// Initialize settings bloc

lib/main_development.dart

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,34 @@ Future<void> main() async {
1414
options
1515
..environment = 'development'
1616
..tracesSampleRate = 1.0
17+
// Don't send request headers and user IP in development
18+
..sendDefaultPii = false
1719
..dsn = dotenv.env['sentryLink'];
1820
},
1921
appRunner: () async {
20-
await bootstrap((
21-
FlutterSecureStorage secureStorage,
22-
SettingsBloc settingsBloc,
23-
) async {
24-
return App(
25-
secureStorage: secureStorage,
26-
settingsBloc: settingsBloc,
27-
);
28-
});
22+
final transaction = Sentry.startTransaction(
23+
'bootstrap()',
24+
'initialization',
25+
bindToScope: true,
26+
);
27+
28+
try {
29+
await bootstrap(transaction, (
30+
FlutterSecureStorage secureStorage,
31+
SettingsBloc settingsBloc,
32+
) async {
33+
return App(
34+
secureStorage: secureStorage,
35+
settingsBloc: settingsBloc,
36+
);
37+
});
38+
} catch (exception) {
39+
transaction
40+
..throwable = exception
41+
..status = const SpanStatus.internalError();
42+
} finally {
43+
await transaction.finish();
44+
}
2945
},
3046
);
3147
}

lib/main_production.dart

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,33 @@ Future<void> main() async {
1414
options
1515
..environment = 'production'
1616
..tracesSampleRate = 1.0
17+
..sendDefaultPii = true
1718
..dsn = dotenv.env['sentryLink'];
1819
},
1920
appRunner: () async {
20-
await bootstrap((
21-
FlutterSecureStorage secureStorage,
22-
SettingsBloc settingsBloc,
23-
) async {
24-
return App(
25-
secureStorage: secureStorage,
26-
settingsBloc: settingsBloc,
27-
);
28-
});
21+
final transaction = Sentry.startTransaction(
22+
'bootstrap()',
23+
'initialization',
24+
bindToScope: true,
25+
);
26+
27+
try {
28+
await bootstrap(transaction, (
29+
FlutterSecureStorage secureStorage,
30+
SettingsBloc settingsBloc,
31+
) async {
32+
return App(
33+
secureStorage: secureStorage,
34+
settingsBloc: settingsBloc,
35+
);
36+
});
37+
} catch (exception) {
38+
transaction
39+
..throwable = exception
40+
..status = const SpanStatus.internalError();
41+
} finally {
42+
await transaction.finish();
43+
}
2944
},
3045
);
3146
}

lib/main_staging.dart

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,33 @@ Future<void> main() async {
1414
options
1515
..environment = 'staging'
1616
..tracesSampleRate = 1.0
17+
..sendDefaultPii = true
1718
..dsn = dotenv.env['sentryLink'];
1819
},
1920
appRunner: () async {
20-
await bootstrap((
21-
FlutterSecureStorage secureStorage,
22-
SettingsBloc settingsBloc,
23-
) async {
24-
return App(
25-
secureStorage: secureStorage,
26-
settingsBloc: settingsBloc,
27-
);
28-
});
21+
final transaction = Sentry.startTransaction(
22+
'bootstrap()',
23+
'initialization',
24+
bindToScope: true,
25+
);
26+
27+
try {
28+
await bootstrap(transaction, (
29+
FlutterSecureStorage secureStorage,
30+
SettingsBloc settingsBloc,
31+
) async {
32+
return App(
33+
secureStorage: secureStorage,
34+
settingsBloc: settingsBloc,
35+
);
36+
});
37+
} catch (exception) {
38+
transaction
39+
..throwable = exception
40+
..status = const SpanStatus.internalError();
41+
} finally {
42+
await transaction.finish();
43+
}
2944
},
3045
);
3146
}

0 commit comments

Comments
 (0)