Przeglądaj źródła

Provide option to opt in to crash analytics

vishnukvmd 2 lat temu
rodzic
commit
b20139f3b8

+ 43 - 22
lib/core/logging/super_logging.dart

@@ -17,6 +17,8 @@ import 'package:package_info_plus/package_info_plus.dart';
 import 'package:path/path.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:sentry_flutter/sentry_flutter.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:uuid/uuid.dart';
 
 typedef FutureOrVoidCallback = FutureOr<void> Function();
 
@@ -144,54 +146,51 @@ class SuperLogging {
   /// The current super logging configuration
   static LogConfig config;
 
+  static SharedPreferences _preferences;
+
+  static const keyShouldReportErrors = "should_report_errors";
+
+  static const keyAnonymousUserID = "anonymous_user_id";
+
   static Future<void> main([LogConfig config]) async {
     config ??= LogConfig();
+
     SuperLogging.config = config;
 
     WidgetsFlutterBinding.ensureInitialized();
 
+    _preferences = await SharedPreferences.getInstance();
+
     appVersion ??= await getAppVersion();
-    final isFDroidClient = await isFDroidBuild();
-    if (isFDroidClient) {
-      config.sentryDsn = null;
-      config.tunnel = null;
-    }
 
-    final enable = config.enableInDebugMode || kReleaseMode;
-    sentryIsEnabled = enable && config.sentryDsn != null && !isFDroidClient;
-    fileIsEnabled = enable && config.logDirPath != null;
+    final loggingEnabled = config.enableInDebugMode || kReleaseMode;
+    sentryIsEnabled =
+        loggingEnabled && config.sentryDsn != null && shouldReportErrors();
+    fileIsEnabled = loggingEnabled && config.logDirPath != null;
 
     if (fileIsEnabled) {
       await setupLogDir();
     }
-    if (sentryIsEnabled) {
-      setupSentry();
-    }
 
     Logger.root.level = Level.ALL;
     Logger.root.onRecord.listen(onLogRecord);
 
-    if (isFDroidClient) {
-      assert(
-        sentryIsEnabled == false,
-        "sentry dsn should be disabled for "
-        "f-droid config  ${config.sentryDsn} & ${config.tunnel}",
-      );
+    if (sentryIsEnabled) {
+      setupSentry();
+    } else {
+      $.info("Sentry is disabled");
     }
 
-    if (!enable) {
+    if (!loggingEnabled) {
       $.info("detected debug mode; sentry & file logging disabled.");
     }
     if (fileIsEnabled) {
       $.info("log file for today: $logFile with prefix ${config.prefix}");
     }
-    if (sentryIsEnabled) {
-      $.info("sentry uploader started");
-    }
 
     if (config.body == null) return;
 
-    if (enable && sentryIsEnabled) {
+    if (loggingEnabled && sentryIsEnabled) {
       await SentryFlutter.init(
         (options) {
           options.dsn = config.sentryDsn;
@@ -296,6 +295,8 @@ class SuperLogging {
   static bool sentryIsEnabled;
 
   static Future<void> setupSentry() async {
+    $.info("Setting up sentry");
+    SuperLogging.setUserID(await _getOrCreateAnonymousUserID());
     await for (final error in sentryQueueControl.stream.asBroadcastStream()) {
       try {
         Sentry.captureException(
@@ -315,6 +316,26 @@ class SuperLogging {
     sentryQueueControl.add(error);
   }
 
+  static bool shouldReportErrors() {
+    if (_preferences.containsKey(keyShouldReportErrors)) {
+      return _preferences.getBool(keyShouldReportErrors);
+    } else {
+      return false;
+    }
+  }
+
+  static Future<void> setShouldReportErrors(bool value) {
+    return _preferences.setBool(keyShouldReportErrors, value);
+  }
+
+  static Future<String> _getOrCreateAnonymousUserID() async {
+    if (!_preferences.containsKey(keyAnonymousUserID)) {
+      //ignore: prefer_const_constructors
+      await _preferences.setString(keyAnonymousUserID, Uuid().v4());
+    }
+    return _preferences.getString(keyAnonymousUserID);
+  }
+
   /// The log file currently in use.
   static File logFile;
 

+ 21 - 1
lib/ui/settings/support_section_widget.dart

@@ -1,17 +1,24 @@
 // @dart=2.9
 
 import 'package:ente_auth/core/constants.dart';
+import 'package:ente_auth/core/logging/super_logging.dart';
 import 'package:ente_auth/theme/ente_theme.dart';
 import 'package:ente_auth/ui/components/captioned_text_widget.dart';
 import 'package:ente_auth/ui/components/expandable_menu_item_widget.dart';
 import 'package:ente_auth/ui/components/menu_item_widget.dart';
+import 'package:ente_auth/ui/components/toggle_switch_widget.dart';
 import 'package:ente_auth/ui/settings/common_settings.dart';
 import 'package:ente_auth/utils/email_util.dart';
 import 'package:flutter/material.dart';
 
-class SupportSectionWidget extends StatelessWidget {
+class SupportSectionWidget extends StatefulWidget {
   const SupportSectionWidget({Key key}) : super(key: key);
 
+  @override
+  State<SupportSectionWidget> createState() => _SupportSectionWidgetState();
+}
+
+class _SupportSectionWidgetState extends State<SupportSectionWidget> {
   @override
   Widget build(BuildContext context) {
     return ExpandableMenuItemWidget(
@@ -53,6 +60,19 @@ class SupportSectionWidget extends StatelessWidget {
           },
         ),
         sectionOptionSpacing,
+        MenuItemWidget(
+          captionedTextWidget: const CaptionedTextWidget(
+            title: "Crash analytics",
+          ),
+          trailingSwitch: ToggleSwitchWidget(
+            value: SuperLogging.shouldReportErrors(),
+            onChanged: (value) async {
+              await SuperLogging.setShouldReportErrors(value);
+              setState(() {});
+            },
+          ),
+        ),
+        sectionOptionSpacing,
       ],
     );
   }