Configure Sentry
This commit is contained in:
parent
546a9234a4
commit
e0b952e516
14 changed files with 222 additions and 43 deletions
|
@ -35,7 +35,7 @@
|
|||
<meta-data android:name="flutterEmbedding" android:value="2"/>
|
||||
|
||||
<meta-data android:name="io.sentry.dsn"
|
||||
android:value="https://8aeb7f013be74f829f8b73b46b3d7a80@sentry.ente.io/8"/>
|
||||
android:value="https://ed4ddd6309b847ba8849935e26e9b648@sentry.ente.io/9"/>
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
|
|
|
@ -81,6 +81,11 @@ PODS:
|
|||
- SDWebImage (5.13.4):
|
||||
- SDWebImage/Core (= 5.13.4)
|
||||
- SDWebImage/Core (5.13.4)
|
||||
- Sentry/HybridSDK (7.30.2)
|
||||
- sentry_flutter (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (= 7.30.2)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_ios (0.0.1):
|
||||
|
@ -111,6 +116,7 @@ DEPENDENCIES:
|
|||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
|
||||
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
|
||||
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
|
||||
- sqflite (from `.symlinks/plugins/sqflite/ios`)
|
||||
|
@ -125,6 +131,7 @@ SPEC REPOS:
|
|||
- OrderedSet
|
||||
- Reachability
|
||||
- SDWebImage
|
||||
- Sentry
|
||||
- SwiftyGif
|
||||
- Toast
|
||||
|
||||
|
@ -163,6 +170,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/path_provider_ios/ios"
|
||||
qr_code_scanner:
|
||||
:path: ".symlinks/plugins/qr_code_scanner/ios"
|
||||
sentry_flutter:
|
||||
:path: ".symlinks/plugins/sentry_flutter/ios"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_ios:
|
||||
|
@ -197,6 +206,8 @@ SPEC CHECKSUMS:
|
|||
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
|
||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
||||
SDWebImage: e5cc87bf736e60f49592f307bdf9e157189298a3
|
||||
Sentry: 9be48e341494bc976c963b05aa4a8ca48308c684
|
||||
sentry_flutter: 544e6376e35b00eef9f0864f8bb7f10a0e204993
|
||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
|
||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||
|
|
|
@ -4,9 +4,10 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:ente_auth/core/constants.dart';
|
||||
// import 'package:ente_auth/core/error-reporting/super_logging.dart';
|
||||
import 'package:ente_auth/core/errors.dart';
|
||||
import 'package:ente_auth/core/event_bus.dart';
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:ente_auth/core/logging/super_logging.dart';
|
||||
import 'package:ente_auth/events/signed_in_event.dart';
|
||||
import 'package:ente_auth/events/signed_out_event.dart';
|
||||
import 'package:ente_auth/models/key_attributes.dart';
|
||||
|
@ -14,7 +15,6 @@ import 'package:ente_auth/models/key_gen_result.dart';
|
|||
import 'package:ente_auth/models/private_key_attributes.dart';
|
||||
import 'package:ente_auth/store/authenticator_db.dart';
|
||||
import 'package:ente_auth/utils/crypto_util.dart';
|
||||
// import 'package:ente_auth/utils/validator_util.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:flutter_sodium/flutter_sodium.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
@ -120,7 +120,7 @@ class Configuration {
|
|||
}
|
||||
await _migrateSecurityStorageToFirstUnlock();
|
||||
}
|
||||
// SuperLogging.setUserID(await _getOrCreateAnonymousUserID());
|
||||
SuperLogging.setUserID(await _getOrCreateAnonymousUserID());
|
||||
}
|
||||
|
||||
Future<void> logout({bool autoLogout = false}) async {
|
||||
|
|
|
@ -4,9 +4,7 @@ const int thumbnailLargeSize = 512;
|
|||
const int compressedThumbnailResolution = 1080;
|
||||
const int thumbnailDataLimit = 100 * 1024;
|
||||
const String sentryDSN =
|
||||
"https://2235e5c99219488ea93da34b9ac1cb68@sentry.ente.io/4";
|
||||
const String sentryDebugDSN =
|
||||
"https://ca5e686dd7f149d9bf94e620564cceba@sentry.ente.io/3";
|
||||
"https://ed4ddd6309b847ba8849935e26e9b648@sentry.ente.io/9";
|
||||
const String sentryTunnel = "https://sentry-reporter.ente.io";
|
||||
const String roadmapURL = "https://roadmap.ente.io";
|
||||
const int microSecondsInDay = 86400000000;
|
||||
|
|
|
@ -7,13 +7,16 @@ import 'dart:collection';
|
|||
import 'dart:core';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ente_auth/core/logging/tunneled_transport.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
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';
|
||||
|
||||
typedef FutureOrVoidCallback = FutureOr<void> Function();
|
||||
|
||||
|
@ -189,17 +192,17 @@ class SuperLogging {
|
|||
if (config.body == null) return;
|
||||
|
||||
if (enable && sentryIsEnabled) {
|
||||
// await SentryFlutter.init(
|
||||
// (options) {
|
||||
// options.dsn = config.sentryDsn;
|
||||
// options.httpClient = http.Client();
|
||||
// if (config.tunnel != null) {
|
||||
// options.transport =
|
||||
// TunneledTransport(Uri.parse(config.tunnel), options);
|
||||
// }
|
||||
// },
|
||||
// appRunner: () => config.body(),
|
||||
// );
|
||||
await SentryFlutter.init(
|
||||
(options) {
|
||||
options.dsn = config.sentryDsn;
|
||||
options.httpClient = http.Client();
|
||||
if (config.tunnel != null) {
|
||||
options.transport =
|
||||
TunneledTransport(Uri.parse(config.tunnel), options);
|
||||
}
|
||||
},
|
||||
appRunner: () => config.body(),
|
||||
);
|
||||
} else {
|
||||
await config.body();
|
||||
}
|
||||
|
@ -207,21 +210,21 @@ class SuperLogging {
|
|||
|
||||
static void setUserID(String userID) async {
|
||||
if (config?.sentryDsn != null) {
|
||||
// Sentry.configureScope((scope) => scope.user = SentryUser(id: userID));
|
||||
Sentry.configureScope((scope) => scope.user = SentryUser(id: userID));
|
||||
$.info("setting sentry user ID to: $userID");
|
||||
}
|
||||
}
|
||||
|
||||
static Future<void> _sendErrorToSentry(Object error, StackTrace stack) async {
|
||||
// try {
|
||||
// await Sentry.captureException(
|
||||
// error,
|
||||
// stackTrace: stack,
|
||||
// );
|
||||
// } catch (e) {
|
||||
// $.info('Sending report to sentry.io failed: $e');
|
||||
// $.info('Original error: $error');
|
||||
// }
|
||||
try {
|
||||
await Sentry.captureException(
|
||||
error,
|
||||
stackTrace: stack,
|
||||
);
|
||||
} catch (e) {
|
||||
$.info('Sending report to sentry.io failed: $e');
|
||||
$.info('Original error: $error');
|
||||
}
|
||||
}
|
||||
|
||||
static String _lastExtraLines = '';
|
||||
|
@ -286,16 +289,16 @@ class SuperLogging {
|
|||
|
||||
static Future<void> setupSentry() async {
|
||||
await for (final error in sentryQueueControl.stream.asBroadcastStream()) {
|
||||
// try {
|
||||
// Sentry.captureException(
|
||||
// error,
|
||||
// );
|
||||
// } catch (e) {
|
||||
// $.fine(
|
||||
// "sentry upload failed; will retry after ${config.sentryRetryDelay}",
|
||||
// );
|
||||
// doSentryRetry(error);
|
||||
// }
|
||||
try {
|
||||
Sentry.captureException(
|
||||
error,
|
||||
);
|
||||
} catch (e) {
|
||||
$.fine(
|
||||
"sentry upload failed; will retry after ${config.sentryRetryDelay}",
|
||||
);
|
||||
doSentryRetry(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,6 +375,6 @@ class SuperLogging {
|
|||
return false;
|
||||
}
|
||||
final pkgName = (await PackageInfo.fromPlatform()).packageName;
|
||||
return pkgName.startsWith("io.ente.photos.fdroid");
|
||||
return pkgName.endsWith("fdroid");
|
||||
}
|
||||
}
|
||||
|
|
141
lib/core/logging/tunneled_transport.dart
Normal file
141
lib/core/logging/tunneled_transport.dart
Normal file
|
@ -0,0 +1,141 @@
|
|||
// @dart=2.9
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
import 'package:sentry/sentry.dart';
|
||||
|
||||
/// A transport is in charge of sending the event to the Sentry server.
|
||||
class TunneledTransport implements Transport {
|
||||
final Uri _tunnel;
|
||||
final SentryOptions _options;
|
||||
|
||||
final Dsn _dsn;
|
||||
|
||||
_CredentialBuilder _credentialBuilder;
|
||||
|
||||
final Map<String, String> _headers;
|
||||
|
||||
factory TunneledTransport(Uri tunnel, SentryOptions options) {
|
||||
return TunneledTransport._(tunnel, options);
|
||||
}
|
||||
|
||||
TunneledTransport._(this._tunnel, this._options)
|
||||
: _dsn = Dsn.parse(_options.dsn),
|
||||
_headers = _buildHeaders(
|
||||
_options.platformChecker.isWeb,
|
||||
_options.sdk.identifier,
|
||||
) {
|
||||
_credentialBuilder = _CredentialBuilder(
|
||||
_dsn,
|
||||
_options.sdk.identifier,
|
||||
_options.clock,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<SentryId> send(SentryEnvelope envelope) async {
|
||||
final streamedRequest = await _createStreamedRequest(envelope);
|
||||
final response = await _options.httpClient
|
||||
.send(streamedRequest)
|
||||
.then(Response.fromStream);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
// body guard to not log the error as it has performance impact to allocate
|
||||
// the body String.
|
||||
if (_options.debug) {
|
||||
_options.logger(
|
||||
SentryLevel.error,
|
||||
'API returned an error, statusCode = ${response.statusCode}, '
|
||||
'body = ${response.body}',
|
||||
);
|
||||
}
|
||||
return const SentryId.empty();
|
||||
} else {
|
||||
_options.logger(
|
||||
SentryLevel.debug,
|
||||
'Envelope ${envelope.header.eventId ?? "--"} was sent successfully.',
|
||||
);
|
||||
}
|
||||
|
||||
final eventId = json.decode(response.body)['id'];
|
||||
if (eventId == null) {
|
||||
return null;
|
||||
}
|
||||
return SentryId.fromId(eventId);
|
||||
}
|
||||
|
||||
Future<StreamedRequest> _createStreamedRequest(
|
||||
SentryEnvelope envelope,
|
||||
) async {
|
||||
final streamedRequest = StreamedRequest('POST', _tunnel);
|
||||
envelope
|
||||
.envelopeStream(_options)
|
||||
.listen(streamedRequest.sink.add)
|
||||
.onDone(streamedRequest.sink.close);
|
||||
|
||||
streamedRequest.headers.addAll(_credentialBuilder.configure(_headers));
|
||||
|
||||
return streamedRequest;
|
||||
}
|
||||
}
|
||||
|
||||
class _CredentialBuilder {
|
||||
final String _authHeader;
|
||||
|
||||
final ClockProvider _clock;
|
||||
|
||||
int get timestamp => _clock().millisecondsSinceEpoch;
|
||||
|
||||
_CredentialBuilder._(String authHeader, ClockProvider clock)
|
||||
: _authHeader = authHeader,
|
||||
_clock = clock;
|
||||
|
||||
factory _CredentialBuilder(
|
||||
Dsn dsn,
|
||||
String sdkIdentifier,
|
||||
ClockProvider clock,
|
||||
) {
|
||||
final authHeader = _buildAuthHeader(
|
||||
publicKey: dsn.publicKey,
|
||||
secretKey: dsn.secretKey,
|
||||
sdkIdentifier: sdkIdentifier,
|
||||
);
|
||||
|
||||
return _CredentialBuilder._(authHeader, clock);
|
||||
}
|
||||
|
||||
static String _buildAuthHeader({
|
||||
String publicKey,
|
||||
String secretKey,
|
||||
String sdkIdentifier,
|
||||
}) {
|
||||
var header = 'Sentry sentry_version=7, sentry_client=$sdkIdentifier, '
|
||||
'sentry_key=$publicKey';
|
||||
|
||||
if (secretKey != null) {
|
||||
header += ', sentry_secret=$secretKey';
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
Map<String, String> configure(Map<String, String> headers) {
|
||||
return headers
|
||||
..addAll(
|
||||
<String, String>{
|
||||
'X-Sentry-Auth': '$_authHeader, sentry_timestamp=$timestamp'
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> _buildHeaders(bool isWeb, String sdkIdentifier) {
|
||||
final headers = {'Content-Type': 'application/x-sentry-envelope'};
|
||||
// NOTE(lejard_h) overriding user agent on VM and Flutter not sure why
|
||||
// for web it use browser user agent
|
||||
if (!isWeb) {
|
||||
headers['User-Agent'] = sdkIdentifier;
|
||||
}
|
||||
return headers;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
// @dart=2.9
|
||||
import "package:ente_auth/app/view/app.dart";
|
||||
import 'package:ente_auth/core/configuration.dart';
|
||||
import 'package:ente_auth/core/constants.dart';
|
||||
import 'package:ente_auth/core/logging/super_logging.dart';
|
||||
import 'package:ente_auth/core/network.dart';
|
||||
import 'package:ente_auth/ente_theme_data.dart';
|
||||
|
@ -47,6 +48,8 @@ Future _runWithLogs(Function() function, {String prefix = ""}) async {
|
|||
body: function,
|
||||
logDirPath: (await getApplicationSupportDirectory()).path + "/logs",
|
||||
maxLogFiles: 5,
|
||||
sentryDsn: sentryDSN,
|
||||
tunnel: sentryTunnel,
|
||||
enableInDebugMode: true,
|
||||
prefix: prefix,
|
||||
),
|
||||
|
|
|
@ -7,12 +7,16 @@
|
|||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
|
||||
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
|
||||
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_linux
|
||||
sentry_flutter
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import connectivity_macos
|
|||
import flutter_secure_storage_macos
|
||||
import package_info_plus_macos
|
||||
import path_provider_macos
|
||||
import sentry_flutter
|
||||
import share_plus_macos
|
||||
import shared_preferences_macos
|
||||
import sqflite
|
||||
|
@ -19,6 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
FlutterSecureStorageMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageMacosPlugin"))
|
||||
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SentryFlutterPlugin.register(with: registry.registrar(forPlugin: "SentryFlutterPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
|
|
14
pubspec.lock
14
pubspec.lock
|
@ -910,6 +910,20 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
sentry:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.15.1"
|
||||
sentry_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry_flutter
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.15.1"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -41,10 +41,8 @@ dependencies:
|
|||
flutter_windowmanager: ^0.2.0
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
# sentry:
|
||||
# path: thirdparty/sentry-dart/dart
|
||||
# sentry_flutter:
|
||||
# path: thirdparty/sentry-dart/flutter
|
||||
sentry: ^6.12.1
|
||||
sentry_flutter: ^6.12.1
|
||||
json_annotation: ^4.5.0
|
||||
fluttertoast: ^8.1.1
|
||||
google_nav_bar: ^5.0.5 #supported
|
||||
|
|
|
@ -7,11 +7,14 @@
|
|||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
SentryFlutterPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("SentryFlutterPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_windows
|
||||
sentry_flutter
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue