Fix log and analytics bugs

This commit is contained in:
problematicconsumer
2023-10-03 21:12:14 +03:30
parent ba071643ce
commit 8f15022443
16 changed files with 86 additions and 57 deletions

View File

@@ -67,12 +67,7 @@ Future<void> lazyBootstrap(
options.tracesSampleRate = 0.25;
options.enableUserInteractionTracing = true;
options.addIntegration(sentryLogger);
options.beforeSend = (event, {hint}) {
return switch (event.throwable) {
ExpectedException _ => null,
_ => event,
};
};
options.beforeSend = sentryBeforeSend;
options.logger = (level, message, {exception, logger, stackTrace}) {
if (level == SentryLevel.fatal) {
_logger.debug(message);

View File

@@ -73,7 +73,7 @@ class ProfilesRepositoryImpl
() async {
final existingProfile = await profilesDao.getProfileByUrl(url);
if (existingProfile case RemoteProfile()) {
loggy.info("profile with url[$url] already exists, updating");
loggy.info("profile with same url already exists, updating");
final baseProfile = markAsActive
? existingProfile.copyWith(active: true)
: existingProfile;
@@ -120,9 +120,9 @@ class ProfilesRepositoryImpl
final parseResult =
await singbox.parseConfig(path, tempPath, false).run();
return parseResult.fold(
(l) async {
loggy.warning("error parsing config: $l");
return left(ProfileFailure.invalidConfig(l.msg));
(err) async {
loggy.warning("error parsing config", err);
return left(ProfileFailure.invalidConfig(err.msg));
},
(_) async {
final profile = LocalProfile(
@@ -267,9 +267,9 @@ class ProfilesRepositoryImpl
final parseResult =
await singbox.parseConfig(path, tempPath, false).run();
return parseResult.fold(
(l) async {
loggy.warning("error parsing config: $l");
return left(ProfileFailure.invalidConfig(l.msg));
(err) async {
loggy.warning("error parsing config", err);
return left(ProfileFailure.invalidConfig(err.msg));
},
(_) async {
final profile = Profile.fromResponse(url, headers);

View File

@@ -8,6 +8,7 @@ part 'app_failure.freezed.dart';
sealed class AppFailure with _$AppFailure, Failure {
const AppFailure._();
@With<UnexpectedFailure>()
const factory AppFailure.unexpected([
Object? error,
StackTrace? stackTrace,

View File

@@ -9,6 +9,7 @@ part 'connection_failure.freezed.dart';
sealed class ConnectionFailure with _$ConnectionFailure, Failure {
const ConnectionFailure._();
@With<UnexpectedFailure>()
const factory ConnectionFailure.unexpected([
Object? error,
StackTrace? stackTrace,

View File

@@ -8,9 +8,10 @@ part 'core_service_failure.freezed.dart';
sealed class CoreServiceFailure with _$CoreServiceFailure, Failure {
const CoreServiceFailure._();
@With<UnexpectedFailure>()
const factory CoreServiceFailure.unexpected(
Object error,
StackTrace stackTrace,
Object? error,
StackTrace? stackTrace,
) = UnexpectedCoreServiceFailure;
@With<ExpectedException>()

View File

@@ -5,6 +5,11 @@ mixin Failure {
({String type, String? message}) present(TranslationsEn t);
}
mixin UnexpectedFailure {
Object? get error;
StackTrace? get stackTrace;
}
/// failures ignored by analytics service etc.
mixin ExpectedException {}

View File

@@ -8,6 +8,7 @@ part 'profiles_failure.freezed.dart';
sealed class ProfileFailure with _$ProfileFailure, Failure {
const ProfileFailure._();
@With<UnexpectedFailure>()
const factory ProfileFailure.unexpected([
Object? error,
StackTrace? stackTrace,

View File

@@ -50,16 +50,16 @@ class AppUpdateNotifier extends _$AppUpdateNotifier with AppLogger {
)
.match(
(err) {
loggy.warning("failed to get latest version, $err");
loggy.warning("failed to get latest version", err);
return state = AppUpdateState.error(err);
},
(remote) {
if (remote.version.compareTo(currentVersion) > 0) {
loggy.info("new version available: $remote");
loggy.debug("new version available: $remote");
return state = AppUpdateState.available(remote);
}
loggy.info(
"already using latest version[$currentVersion], remote: $remote",
"already using latest version[$currentVersion], remote: [${remote.version}]",
);
return state = const AppUpdateState.notAvailable();
},

View File

@@ -47,9 +47,9 @@ class ConnectivityController extends _$ConnectivityController with AppLogger {
return _disconnect();
}
loggy.debug("reconnecting, profile: [$profileId]");
await _core.restart(profileId).mapLeft((l) {
loggy.warning("error reconnecting: $l");
state = AsyncError(l, StackTrace.current);
await _core.restart(profileId).mapLeft((err) {
loggy.warning("error reconnecting", err);
state = AsyncError(err, StackTrace.current);
}).run();
}
}
@@ -67,16 +67,16 @@ class ConnectivityController extends _$ConnectivityController with AppLogger {
Future<void> _connect() async {
final activeProfile = await ref.read(activeProfileProvider.future);
await _core.start(activeProfile!.id).mapLeft((l) {
loggy.warning("error connecting: $l");
state = AsyncError(l, StackTrace.current);
await _core.start(activeProfile!.id).mapLeft((err) {
loggy.warning("error connecting", err);
state = AsyncError(err, StackTrace.current);
}).run();
}
Future<void> _disconnect() async {
await _core.stop().mapLeft((l) {
loggy.warning("error disconnecting: $l");
state = AsyncError(l, StackTrace.current);
await _core.stop().mapLeft((err) {
loggy.warning("error disconnecting", err);
state = AsyncError(err, StackTrace.current);
}).run();
}
}

View File

@@ -30,9 +30,9 @@ class ProfileDetailNotifier extends _$ProfileDetailNotifier with AppLogger {
}
final failureOrProfile = await _profilesRepo.get(id).run();
return failureOrProfile.match(
(l) {
loggy.warning('failed to load profile, $l');
throw l;
(err) {
loggy.warning('failed to load profile', err);
throw err;
},
(profile) {
if (profile == null) {

View File

@@ -43,9 +43,9 @@ class ProfilesNotifier extends _$ProfilesNotifier with AppLogger {
Future<Unit> selectActiveProfile(String id) async {
loggy.debug('changing active profile to: [$id]');
return _profilesRepo.setAsActive(id).getOrElse((f) {
loggy.warning('failed to set [$id] as active profile, $f');
throw f;
return _profilesRepo.setAsActive(id).getOrElse((err) {
loggy.warning('failed to set [$id] as active profile', err);
throw err;
}).run();
}
@@ -58,9 +58,9 @@ class ProfilesNotifier extends _$ProfilesNotifier with AppLogger {
return ref
.read(profilesRepositoryProvider)
.addByUrl(link.url, markAsActive: markAsActive)
.getOrElse((l) {
loggy.warning("failed to add profile: $l");
throw l;
.getOrElse((err) {
loggy.warning("failed to add profile", err);
throw err;
}).run();
} else if (LinkParser.protocol(rawInput) case (final parsed)?) {
loggy.debug("adding profile, content");
@@ -71,9 +71,9 @@ class ProfilesNotifier extends _$ProfilesNotifier with AppLogger {
name: parsed.name,
markAsActive: markAsActive,
)
.getOrElse((l) {
loggy.warning("failed to add profile: $l");
throw l;
.getOrElse((err) {
loggy.warning("failed to add profile", err);
throw err;
}).run();
} else {
loggy.debug("invalid content");
@@ -93,9 +93,9 @@ class ProfilesNotifier extends _$ProfilesNotifier with AppLogger {
Future<void> deleteProfile(Profile profile) async {
loggy.debug('deleting profile: ${profile.name}');
await _profilesRepo.delete(profile.id).mapLeft(
(f) {
loggy.warning('failed to delete profile, $f');
throw f;
(err) {
loggy.warning('failed to delete profile', err);
throw err;
},
).run();
}

View File

@@ -60,9 +60,9 @@ class ProxiesNotifier extends _$ProxiesNotifier with AppLogger {
.watchOutbounds()
.map(
(event) => event.getOrElse(
(f) {
loggy.warning("error receiving proxies: $f");
throw f;
(err) {
loggy.warning("error receiving proxies", err);
throw err;
},
),
)
@@ -105,9 +105,9 @@ class ProxiesNotifier extends _$ProxiesNotifier with AppLogger {
await ref
.read(coreFacadeProvider)
.selectOutbound(groupTag, outboundTag)
.getOrElse((l) {
loggy.warning("error selecting outbound", l);
throw l;
.getOrElse((err) {
loggy.warning("error selecting outbound", err);
throw err;
}).run();
state = AsyncData(
[
@@ -122,9 +122,9 @@ class ProxiesNotifier extends _$ProxiesNotifier with AppLogger {
Future<void> urlTest(String groupTag) async {
loggy.debug("testing group: [$groupTag]");
if (state case AsyncData()) {
await ref.read(coreFacadeProvider).urlTest(groupTag).getOrElse((l) {
loggy.warning("error testing group", l);
throw l;
await ref.read(coreFacadeProvider).urlTest(groupTag).getOrElse((err) {
loggy.warning("error testing group", err);
throw err;
}).run();
}
}

View File

@@ -25,9 +25,9 @@ Future<List<InstalledPackageInfo>> installedPackagesInfo(
return ref
.watch(platformSettingsProvider)
.getInstalledPackages()
.getOrElse((l) {
_logger.warning("error getting installed packages: $l");
throw l;
.getOrElse((err) {
_logger.warning("error getting installed packages", err);
throw err;
}).run();
}
@@ -40,9 +40,9 @@ Future<ImageProvider> packageIcon(
final bytes = await ref
.watch(platformSettingsProvider)
.getPackageIcon(packageName)
.getOrElse((l) {
_logger.warning("error getting package icon: $l");
throw l;
.getOrElse((err) {
_logger.warning("error getting package icon", err);
throw err;
}).run();
return MemoryImage(bytes);
}

View File

@@ -1,3 +1,4 @@
import 'package:hiddify/utils/sentry_utils.dart';
import 'package:loggy/loggy.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
@@ -33,6 +34,8 @@ class SentryLoggyIntegration extends LoggyPrinter
@override
Future<void> onLog(LogRecord record) async {
if (!canSendEvent(record.error)) return;
if (_shouldLog(record.level, _minEventLevel)) {
await _hub.captureEvent(
record.toEvent(),

View File

@@ -0,0 +1,21 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:hiddify/domain/failures.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
FutureOr<SentryEvent?> sentryBeforeSend(SentryEvent event, {Hint? hint}) {
if (canSendEvent(event.throwable)) return event;
return null;
}
bool canSendEvent(dynamic throwable) {
return switch (throwable) {
UnexpectedFailure(:final error) => canSendEvent(error),
DioException _ => false,
SocketException _ => false,
ExpectedException _ => false,
_ => true,
};
}

View File

@@ -13,6 +13,7 @@ export 'placeholders.dart';
export 'platform_utils.dart';
export 'sentry_loggy_integration.dart';
export 'sentry_riverpod_observer.dart';
export 'sentry_utils.dart';
export 'text_utils.dart';
export 'uri_utils.dart';
export 'validators.dart';