Skip to content

Commit

Permalink
feat: add bugsee unhandled exception log method to bugsee manager
Browse files Browse the repository at this point in the history
  • Loading branch information
koukibadr committed Nov 15, 2024
1 parent 3bdbbff commit 98757c3
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/app/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pluginManagement {

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version '7.4.2' apply false
id "com.android.application" version '7.3.0' apply false
// START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false
// END: FlutterFire Configuration
Expand Down
14 changes: 9 additions & 5 deletions src/app/lib/access/bugsee/bugsee_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import 'package:shared_preferences/shared_preferences.dart';
abstract interface class BugseeRepository {
factory BugseeRepository() = _BugseeRepository;

///Load the current bugsee configuration stored in shared prefs.
/// Load the current bugsee configuration stored in shared prefs.
Future<BugseeConfigurationData> getBugseeConfiguration();

///Update the current Bugsee enabled flag in shared prefs.
/// Update the current Bugsee enabled flag in shared prefs.
Future setIsBugseeEnabled(bool isBugseeEnabled);

///Update the current video captured or not flag in shared prefs.
/// Update the current video captured or not flag in shared prefs.
Future setIsVideoCaptureEnabled(bool isVideoCaptureEnabled);
}

Expand All @@ -38,7 +38,9 @@ final class _BugseeRepository implements BugseeRepository {
);

if (!isSaved) {
throw const PersistenceException();
throw PersistenceException(
message: 'Error while setting $_bugseeEnabledKey $isBugseeEnabled',
);
}
}

Expand All @@ -52,7 +54,9 @@ final class _BugseeRepository implements BugseeRepository {
);

if (!isSaved) {
throw const PersistenceException();
throw PersistenceException(
message: 'Error while setting $_videoCaptureKey $isVideoCaptureEnabled',
);
}
}
}
5 changes: 4 additions & 1 deletion src/app/lib/access/persistence_exception.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/// Exception thrown when something couldn't be persisted in the shared preference.
/// It was created due to https://github.com/flutter/flutter/issues/146070.
final class PersistenceException implements Exception {
const PersistenceException();
/// A descriptive message detailing the persistence exception
final String? message;

const PersistenceException({this.message});
}
117 changes: 74 additions & 43 deletions src/app/lib/business/bugsee/bugsee_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,41 @@ abstract interface class BugseeManager {
required BugseeRepository bugseeRepository,
}) = _BugseeManager;

bool get configurationHasChanged;
bool get isRequireRestart;

bool get bugseeIsEnabled;
bool get captureVideoIsEnabled;
bool get isValidConfiguration;

///initialize bugsee with given token
///bugsee is not available in debug mode
///* [bugseeToken]: nullable bugsee token, if null bugsee won't be initialized make sure you provide
///[BUGSEE_TOKEN] in the env using `--dart-define` or `launch.json` on vscode
/// initialize bugsee with given token
/// bugsee is not available in debug mode
/// * [bugseeToken]: nullable bugsee token, if null bugsee won't be initialized make sure you provide
/// [BUGSEE_TOKEN] in the env using `--dart-define` or `launch.json` on vscode
Future<void> initialize({
String? bugseeToken,
});

///Manually log a provided exception with a stack trace
/// Manually log a provided exception with a stack trace
/// (medium severity exception in Bugsee dashboard)
Future<void> logException({
required Exception exception,
StackTrace? stackTrace,
});

///Manually update the current BugseeEnabled flag in shared prefs and in current manager singleton.
Future<void> updateBugseeEnabledValue(bool isBugseeEnabled);
/// Manually log an unhandled exception with a stack trace
/// (critical severity exception in Bugsee dashboard)
Future<void> logUnhandledException({
required Exception exception,
StackTrace? stackTrace,
});

/// Manually update the current BugseeEnabled flag in shared prefs and in current manager singleton.
Future<void> setIsBugseeEnabled(bool isBugseeEnabled);

///Manually update the current enableVideoCapture flag in shared prefs and in current manager singleton.
Future<void> updateIsVideoCuptureValue(bool isBugseeEnabled);
/// Manually update the current enableVideoCapture flag in shared prefs and in current manager singleton.
Future<void> setIsVideoCaptureEnabled(bool isBugseeEnabled);

///Manually shows the built-in capture log report screen of Bugsee.
/// Manually shows the built-in capture log report screen of Bugsee.
Future<void> showCaptureLogReport();
}

Expand All @@ -58,7 +66,7 @@ final class _BugseeManager implements BugseeManager {
});

@override
bool configurationHasChanged = false;
bool isRequireRestart = false;

@override
bool bugseeIsEnabled = false;
Expand All @@ -70,7 +78,7 @@ final class _BugseeManager implements BugseeManager {
bool isValidConfiguration = true;

late bool _isBugSeeInitialized;
late BugseeLaunchOptions launchOptions;
BugseeLaunchOptions? launchOptions;

@override
Future<void> initialize({
Expand All @@ -79,48 +87,56 @@ final class _BugseeManager implements BugseeManager {
BugseeConfigurationData bugseeConfigurationData =
await bugseeRepository.getBugseeConfiguration();

initializeLaunchOptions();
launchOptions = initializeLaunchOptions();
_isBugSeeInitialized = false;

if (kDebugMode ||
bugseeToken == null ||
!RegExp(bugseeTokenFormat).hasMatch(bugseeToken)) {
if (kDebugMode) {
isValidConfiguration = false;
if (!kDebugMode) {
logger.i(
"BUGSEE: token is null or invalid, bugsee won't be initialized",
);
} else {
logger.i("BUGSEE: deactivated in debug mode");
}
logger.i("BUGSEE: deactivated in debug mode");
return;
} else if (bugseeConfigurationData.isBugseeEnabled ?? true) {
HttpOverrides.global = Bugsee.defaultHttpOverrides;
await Bugsee.launch(
bugseeToken,
appRunCallback: (isBugseeLaunched) {
if (!isBugseeLaunched) {
logger.e(
"BUGSEE: not initialized, verify bugsee token configuration",
);
}
_isBugSeeInitialized = isBugseeLaunched;
},
launchOptions: launchOptions,
}

if (bugseeToken == null ||
!RegExp(bugseeTokenFormat).hasMatch(bugseeToken)) {
isValidConfiguration = false;
logger.i(
"BUGSEE: token is null or invalid, bugsee won't be initialized",
);
return;
}

if (bugseeConfigurationData.isBugseeEnabled ?? true) {
await launchBugseeLogger(bugseeToken);
}

bugseeIsEnabled = _isBugSeeInitialized;
captureVideoIsEnabled = _isBugSeeInitialized &&
(bugseeConfigurationData.isVideoCaptureEnabled ?? true);
}

Future initializeLaunchOptions() async {
Future launchBugseeLogger(String bugseeToken) async {
HttpOverrides.global = Bugsee.defaultHttpOverrides;
await Bugsee.launch(
bugseeToken,
appRunCallback: (isBugseeLaunched) {
if (!isBugseeLaunched) {
logger.e(
"BUGSEE: not initialized, verify bugsee token configuration",
);
}
_isBugSeeInitialized = isBugseeLaunched;
},
launchOptions: launchOptions,
);
}

BugseeLaunchOptions? initializeLaunchOptions() {
if (Platform.isAndroid) {
launchOptions = AndroidLaunchOptions();
return AndroidLaunchOptions();
} else if (Platform.isIOS) {
launchOptions = IOSLaunchOptions();
return IOSLaunchOptions();
}
return null;
}

@override
Expand All @@ -134,17 +150,32 @@ final class _BugseeManager implements BugseeManager {
}

@override
Future<void> updateBugseeEnabledValue(bool isBugseeEnabled) async {
Future<void> logUnhandledException({
required Exception exception,
StackTrace? stackTrace,
}) async {
if (bugseeIsEnabled) {
await Bugsee.logUnhandledException(exception);
}
}

@override
Future<void> setIsBugseeEnabled(bool isBugseeEnabled) async {
if (isValidConfiguration) {
await bugseeRepository.setIsBugseeEnabled(isBugseeEnabled);

isRequireRestart = _isBugSeeInitialized && isBugseeEnabled;
bugseeIsEnabled = isBugseeEnabled;
configurationHasChanged = bugseeIsEnabled != _isBugSeeInitialized;
captureVideoIsEnabled = bugseeIsEnabled;

if (!isRequireRestart) {
await Bugsee.stop();
}
}
}

@override
Future<void> updateIsVideoCuptureValue(bool isVideoCaptureEnabled) async {
Future<void> setIsVideoCaptureEnabled(bool isVideoCaptureEnabled) async {
if (bugseeIsEnabled) {
captureVideoIsEnabled = isVideoCaptureEnabled;
await bugseeRepository.setIsVideoCaptureEnabled(isVideoCaptureEnabled);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class _BugseeConfigurationWidgetState extends State<BugseeConfigurationWidget> {
super.initState();
isConfigEnabled = bugseeManager.bugseeIsEnabled;
isCaptureVideoEnabled = bugseeManager.captureVideoIsEnabled;
requireRestart = bugseeManager.configurationHasChanged;
requireRestart = bugseeManager.isRequireRestart;
}

@override
Expand Down Expand Up @@ -53,7 +53,7 @@ class _BugseeConfigurationWidgetState extends State<BugseeConfigurationWidget> {
Container(
color: const Color.fromARGB(170, 255, 0, 0),
child: const Text(
"Bugsee config has changed please restart the app.",
"In order to reactivate Bugsee logger restart the app.",
style: TextStyle(
color: Colors.white,
fontSize: 20,
Expand All @@ -66,19 +66,19 @@ class _BugseeConfigurationWidgetState extends State<BugseeConfigurationWidget> {
label: 'Bugsee enabled',
value: isConfigEnabled,
onChanged: (value) async {
bugseeManager.updateBugseeEnabledValue(value);
await bugseeManager.setIsBugseeEnabled(value);
setState(() {
isConfigEnabled = bugseeManager.bugseeIsEnabled;
isCaptureVideoEnabled = bugseeManager.captureVideoIsEnabled;
requireRestart = bugseeManager.configurationHasChanged;
requireRestart = bugseeManager.isRequireRestart;
});
},
),
DiagnosticSwitch(
label: 'Video capture enabled',
value: isCaptureVideoEnabled,
onChanged: (value) async {
bugseeManager.updateIsVideoCuptureValue(value);
await bugseeManager.setIsVideoCaptureEnabled(value);
setState(() {
isCaptureVideoEnabled = bugseeManager.captureVideoIsEnabled;
});
Expand All @@ -92,6 +92,12 @@ class _BugseeConfigurationWidgetState extends State<BugseeConfigurationWidget> {
bugseeManager.logException(exception: Exception());
},
),
DiagnosticButton(
label: 'Log an unhandled exception',
onPressed: () {
bugseeManager.logUnhandledException(exception: Exception());
},
),
DiagnosticButton(
label: 'Show report dialog',
onPressed: () {
Expand Down

0 comments on commit 98757c3

Please sign in to comment.