Files
GitJournal/lib/error_reporting.dart
Vishesh Handa b9b53f28c4 Log some exceptions are warnings
These aren't really a problem, but it's still interesting to know if
they are happening.
2020-05-31 02:00:00 +02:00

150 lines
3.8 KiB
Dart

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';
import 'package:gitjournal/.env.dart';
SentryClient _sentryClient;
Future<SentryClient> _initSentry() async {
return SentryClient(
dsn: environment['sentry'],
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,
),
),
userContext: User(
id: Settings.instance.pseudoId,
),
);
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<void> initCrashlytics() async {
if (reportCrashes) {
await FlutterCrashlytics().initialize();
}
}
Future<void> reportError(Object error, StackTrace stackTrace) async {
if (reportCrashes) {
captureSentryException(error, stackTrace);
}
print("Uncaught Exception: $error");
print(stackTrace);
}
Future<void> logException(Exception e, StackTrace stackTrace) async {
if (!reportCrashes) {
return;
}
await captureSentryException(e, stackTrace);
return FlutterCrashlytics().logException(e, stackTrace);
}
Future<void> logExceptionWarning(Exception e, StackTrace stackTrace) async {
if (!reportCrashes) {
return;
}
await captureSentryException(e, stackTrace, level: SeverityLevel.warning);
return FlutterCrashlytics().logException(e, stackTrace);
}
List<Breadcrumb> breadcrumbs = [];
void captureErrorBreadcrumb({
@required String name,
Map<String, String> parameters,
}) {
var b = Breadcrumb(name, DateTime.now(), data: parameters);
breadcrumbs.add(b);
}
Future<void> captureSentryException(
Object exception,
StackTrace stackTrace, {
SeverityLevel level = SeverityLevel.error,
}) async {
try {
final sentry = await getSentryClient();
final Event event = Event(
exception: exception,
stackTrace: stackTrace,
breadcrumbs: breadcrumbs,
level: level,
);
return sentry.capture(event: event);
} catch (e) {
print("Failed to report with Sentry: $e");
}
}