mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-28 18:03:14 +08:00
Move error reporting to its own file
* Avoid passing Flutter errors to its Zone handler, this doesn't always catch the errors * Catch the current isolate's errors. I haven't been able to test this out, but lets see.
This commit is contained in:
115
lib/error_reporting.dart
Normal file
115
lib/error_reporting.dart
Normal file
@ -0,0 +1,115 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info/device_info.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_crashlytics/flutter_crashlytics.dart';
|
||||
import 'package:gitjournal/app.dart';
|
||||
import 'package:gitjournal/settings.dart';
|
||||
import 'package:package_info/package_info.dart';
|
||||
import 'package:sentry/sentry.dart';
|
||||
|
||||
SentryClient _sentryClient;
|
||||
Future<SentryClient> _initSentry() async {
|
||||
return SentryClient(
|
||||
dsn: 'https://35f34dbec289435fbe16483faacf49a5@sentry.io/5168082',
|
||||
environmentAttributes: await _environmentEvent,
|
||||
);
|
||||
}
|
||||
|
||||
Future<SentryClient> getSentryClient() async {
|
||||
return _sentryClient ??= await _initSentry();
|
||||
}
|
||||
|
||||
Future<Event> get _environmentEvent async {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
final deviceInfoPlugin = DeviceInfoPlugin();
|
||||
OperatingSystem os;
|
||||
Device device;
|
||||
if (Platform.isAndroid) {
|
||||
final androidInfo = await deviceInfoPlugin.androidInfo;
|
||||
os = OperatingSystem(
|
||||
name: 'android',
|
||||
version: androidInfo.version.release,
|
||||
);
|
||||
device = Device(
|
||||
model: androidInfo.model,
|
||||
manufacturer: androidInfo.manufacturer,
|
||||
modelId: androidInfo.product,
|
||||
);
|
||||
} else if (Platform.isIOS) {
|
||||
final iosInfo = await deviceInfoPlugin.iosInfo;
|
||||
os = OperatingSystem(
|
||||
name: iosInfo.systemName,
|
||||
version: iosInfo.systemVersion,
|
||||
);
|
||||
device = Device(
|
||||
model: iosInfo.utsname.machine,
|
||||
family: iosInfo.model,
|
||||
manufacturer: 'Apple',
|
||||
);
|
||||
}
|
||||
final environment = Event(
|
||||
release: '${packageInfo.version} (${packageInfo.buildNumber})',
|
||||
contexts: Contexts(
|
||||
operatingSystem: os,
|
||||
device: device,
|
||||
app: App(
|
||||
name: packageInfo.appName,
|
||||
version: packageInfo.version,
|
||||
build: packageInfo.buildNumber,
|
||||
),
|
||||
),
|
||||
);
|
||||
return environment;
|
||||
}
|
||||
|
||||
void flutterOnErrorHandler(FlutterErrorDetails details) {
|
||||
if (reportCrashes == true) {
|
||||
// vHanda: This doesn't always call our zone error handler, why?
|
||||
// Zone.current.handleUncaughtError(details.exception, details.stack);
|
||||
reportError(details.exception, details.stack);
|
||||
} else {
|
||||
FlutterError.dumpErrorToConsole(details);
|
||||
}
|
||||
}
|
||||
|
||||
bool get reportCrashes => _reportCrashes ??= _initReportCrashes();
|
||||
bool _reportCrashes;
|
||||
bool _initReportCrashes() {
|
||||
return !JournalApp.isInDebugMode && Settings.instance.collectCrashReports;
|
||||
}
|
||||
|
||||
Future<FlutterCrashlytics> getCrashlyticsClient() async {
|
||||
return _crashlytics ??= await _initCrashlytics();
|
||||
}
|
||||
|
||||
FlutterCrashlytics _crashlytics;
|
||||
Future<FlutterCrashlytics> _initCrashlytics() async {
|
||||
await FlutterCrashlytics().initialize();
|
||||
return FlutterCrashlytics();
|
||||
}
|
||||
|
||||
Future<void> reportError(Object error, StackTrace stackTrace) async {
|
||||
if (reportCrashes) {
|
||||
try {
|
||||
final sentry = await getSentryClient();
|
||||
sentry.captureException(
|
||||
exception: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
} catch (e) {
|
||||
print("Failed to report with Sentry: $e");
|
||||
}
|
||||
|
||||
try {
|
||||
final crashlytics = await getCrashlyticsClient();
|
||||
crashlytics.reportCrash(error, stackTrace, forceCrash: false);
|
||||
} catch (e) {
|
||||
print("Failed to report with Crashlytics: $e");
|
||||
}
|
||||
}
|
||||
|
||||
print("Uncaught Exception: $error");
|
||||
print(stackTrace);
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import 'dart:async';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart' as foundation;
|
||||
|
||||
import 'package:flutter_crashlytics/flutter_crashlytics.dart';
|
||||
import 'package:sentry/sentry.dart';
|
||||
import 'package:gitjournal/error_reporting.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:gitjournal/app.dart';
|
||||
@ -17,35 +17,18 @@ void main() async {
|
||||
Settings.instance.load(pref);
|
||||
|
||||
JournalApp.isInDebugMode = foundation.kDebugMode;
|
||||
var reportCrashes =
|
||||
!JournalApp.isInDebugMode && Settings.instance.collectCrashReports;
|
||||
FlutterError.onError = flutterOnErrorHandler;
|
||||
|
||||
FlutterError.onError = (FlutterErrorDetails details) {
|
||||
if (!reportCrashes) {
|
||||
FlutterError.dumpErrorToConsole(details);
|
||||
} else {
|
||||
Zone.current.handleUncaughtError(details.exception, details.stack);
|
||||
}
|
||||
};
|
||||
Isolate.current.addErrorListener(RawReceivePort((dynamic pair) async {
|
||||
var isolateError = pair as List<dynamic>;
|
||||
assert(isolateError.length == 2);
|
||||
assert(isolateError.first.runtimeType == Error);
|
||||
assert(isolateError.last.runtimeType == StackTrace);
|
||||
|
||||
print("Report Crashes: $reportCrashes");
|
||||
if (reportCrashes) {
|
||||
await FlutterCrashlytics().initialize();
|
||||
}
|
||||
|
||||
var sentry = SentryClient(
|
||||
dsn: 'https://35f34dbec289435fbe16483faacf49a5@sentry.io/5168082',
|
||||
);
|
||||
await reportError(isolateError.first, isolateError.last);
|
||||
}).sendPort);
|
||||
|
||||
runZoned<Future<void>>(() async {
|
||||
await JournalApp.main(pref);
|
||||
}, onError: (Object error, StackTrace stackTrace) async {
|
||||
print("Uncaught Exception: " + error.toString());
|
||||
print(stackTrace);
|
||||
FlutterCrashlytics().reportCrash(error, stackTrace, forceCrash: false);
|
||||
sentry.captureException(
|
||||
exception: error,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
});
|
||||
}, onError: reportError);
|
||||
}
|
||||
|
Reference in New Issue
Block a user