Change initialization and logging
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_loggy/flutter_loggy.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:hiddify/core/analytics/analytics_controller.dart';
|
||||
import 'package:hiddify/core/app_info/app_info_provider.dart';
|
||||
import 'package:hiddify/core/directories/directories_provider.dart';
|
||||
import 'package:hiddify/core/logger/logger.dart';
|
||||
import 'package:hiddify/core/logger/logger_controller.dart';
|
||||
import 'package:hiddify/core/model/environment.dart';
|
||||
import 'package:hiddify/core/preferences/general_preferences.dart';
|
||||
import 'package:hiddify/core/preferences/preferences_migration.dart';
|
||||
@@ -18,7 +22,6 @@ import 'package:hiddify/features/profile/notifier/active_profile_notifier.dart';
|
||||
import 'package:hiddify/features/system_tray/system_tray_controller.dart';
|
||||
import 'package:hiddify/services/auto_start_service.dart';
|
||||
import 'package:hiddify/services/deep_link_service.dart';
|
||||
import 'package:hiddify/services/service_providers.dart';
|
||||
import 'package:hiddify/singbox/service/singbox_service_provider.dart';
|
||||
import 'package:hiddify/utils/utils.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -26,20 +29,20 @@ import 'package:loggy/loggy.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
final _logger = Loggy('bootstrap');
|
||||
const _testCrashReport = false;
|
||||
final _loggers = MultiLogPrinter(const PrettyPrinter(), []);
|
||||
|
||||
Future<void> lazyBootstrap(
|
||||
WidgetsBinding widgetsBinding,
|
||||
Environment env,
|
||||
) async {
|
||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
if (PlatformUtils.isDesktop) await windowManager.ensureInitialized();
|
||||
|
||||
final sentryLogger = SentryLoggyIntegration();
|
||||
_loggers.addPrinter(sentryLogger);
|
||||
Loggy.initLoggy();
|
||||
Loggy.initLoggy(logPrinter: const PrettyDeveloperPrinter());
|
||||
|
||||
FlutterError.onError = Logger.logFlutterError;
|
||||
WidgetsBinding.instance.platformDispatcher.onError =
|
||||
Logger.logPlatformDispatcherError;
|
||||
|
||||
final stopWatch = Stopwatch()..start();
|
||||
if (PlatformUtils.isDesktop) await windowManager.ensureInitialized();
|
||||
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
@@ -47,65 +50,65 @@ Future<void> lazyBootstrap(
|
||||
],
|
||||
);
|
||||
|
||||
final appInfo = await container.read(appInfoProvider.future);
|
||||
|
||||
await container.read(sharedPreferencesProvider.future);
|
||||
final enableAnalytics = container.read(enableAnalyticsProvider);
|
||||
|
||||
await SentryFlutter.init(
|
||||
(options) {
|
||||
if ((enableAnalytics && !kDebugMode) || _testCrashReport) {
|
||||
options.dsn = Environment.sentryDSN;
|
||||
} else {
|
||||
options.dsn = "";
|
||||
}
|
||||
|
||||
options.environment = env.name;
|
||||
options.dist = appInfo.release.name;
|
||||
options.debug = kDebugMode;
|
||||
options.enableNativeCrashHandling = true;
|
||||
options.enableNdkScopeSync = true;
|
||||
options.attachThreads = true;
|
||||
options.tracesSampleRate = 0.25;
|
||||
options.enableUserInteractionTracing = true;
|
||||
options.addIntegration(sentryLogger);
|
||||
options.beforeSend = sentryBeforeSend;
|
||||
options.logger = (level, message, {exception, logger, stackTrace}) {
|
||||
if (level == SentryLevel.fatal) {
|
||||
_logger.debug(message);
|
||||
}
|
||||
};
|
||||
},
|
||||
appRunner: () => _lazyBootstrap(widgetsBinding, container, env),
|
||||
await _init(
|
||||
"directories",
|
||||
() => container.read(appDirectoriesProvider.future),
|
||||
);
|
||||
}
|
||||
LoggerController.init(container.read(logPathResolverProvider).appFile().path);
|
||||
|
||||
Future<void> _lazyBootstrap(
|
||||
WidgetsBinding widgetsBinding,
|
||||
ProviderContainer container,
|
||||
Environment env,
|
||||
) async {
|
||||
try {
|
||||
await PreferencesMigration(
|
||||
sharedPreferences: container.read(sharedPreferencesProvider).requireValue,
|
||||
).migrate();
|
||||
} catch (e) {
|
||||
_logger.error("preferences migration failed", e);
|
||||
if (env == Environment.dev) rethrow;
|
||||
_logger.info("clearing preferences");
|
||||
await container.read(sharedPreferencesProvider).requireValue.clear();
|
||||
final appInfo = await _init(
|
||||
"app info",
|
||||
() => container.read(appInfoProvider.future),
|
||||
);
|
||||
await _init(
|
||||
"preferences",
|
||||
() => container.read(sharedPreferencesProvider.future),
|
||||
);
|
||||
|
||||
final enableAnalytics = container.read(analyticsControllerProvider);
|
||||
if (enableAnalytics) {
|
||||
await _init(
|
||||
"analytics",
|
||||
() => container
|
||||
.read(analyticsControllerProvider.notifier)
|
||||
.enableAnalytics(),
|
||||
);
|
||||
}
|
||||
|
||||
await _init(
|
||||
"preferences migration",
|
||||
() async {
|
||||
try {
|
||||
await PreferencesMigration(
|
||||
sharedPreferences:
|
||||
container.read(sharedPreferencesProvider).requireValue,
|
||||
).migrate();
|
||||
} catch (e, stackTrace) {
|
||||
Logger.bootstrap.error("preferences migration failed", e, stackTrace);
|
||||
if (env == Environment.dev) rethrow;
|
||||
Logger.bootstrap.info("clearing preferences");
|
||||
await container.read(sharedPreferencesProvider).requireValue.clear();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
final debug = container.read(debugModeNotifierProvider) || kDebugMode;
|
||||
|
||||
final filesEditor = container.read(filesEditorServiceProvider);
|
||||
await filesEditor.init();
|
||||
await container.read(logRepositoryProvider.future);
|
||||
await container.read(geoAssetRepositoryProvider.future);
|
||||
await container.read(profileRepositoryProvider.future);
|
||||
await _init(
|
||||
"logs repository",
|
||||
() => container.read(logRepositoryProvider.future),
|
||||
);
|
||||
await _init("logger controller", () => LoggerController.postInit(debug));
|
||||
Logger.bootstrap.info(appInfo.format());
|
||||
|
||||
initLoggers(container.read, debug);
|
||||
_logger.info(container.read(appInfoProvider).requireValue.format());
|
||||
await _init(
|
||||
"geo assets repository",
|
||||
() => container.read(geoAssetRepositoryProvider.future),
|
||||
);
|
||||
await _init(
|
||||
"profile repository",
|
||||
() => container.read(profileRepositoryProvider.future),
|
||||
);
|
||||
|
||||
final silentStart = container.read(silentStartNotifierProvider);
|
||||
if (silentStart) {
|
||||
@@ -113,31 +116,41 @@ Future<void> _lazyBootstrap(
|
||||
}
|
||||
|
||||
if (PlatformUtils.isDesktop) {
|
||||
_logger.debug("initializing [Auto Start Service] and [Window Controller]");
|
||||
await container.read(autoStartServiceProvider.future);
|
||||
await container.read(windowControllerProvider.future);
|
||||
await _init(
|
||||
"auto start service",
|
||||
() => container.read(autoStartServiceProvider.future),
|
||||
);
|
||||
await _init(
|
||||
"window controller",
|
||||
() => container.read(windowControllerProvider.future),
|
||||
);
|
||||
}
|
||||
|
||||
await container.read(singboxServiceProvider).init();
|
||||
_logger.debug("initialized [Singbox Service]");
|
||||
await _init(
|
||||
"sing-box",
|
||||
() => container.read(singboxServiceProvider).init(),
|
||||
);
|
||||
|
||||
await _safeInit(
|
||||
"active profile",
|
||||
() => container.read(activeProfileProvider.future),
|
||||
);
|
||||
await _init(
|
||||
"deep link service",
|
||||
() => container.read(deepLinkServiceProvider.future),
|
||||
);
|
||||
|
||||
await container.read(activeProfileProvider.future);
|
||||
await container.read(deepLinkServiceProvider.future);
|
||||
if (PlatformUtils.isDesktop) {
|
||||
try {
|
||||
await container
|
||||
.read(systemTrayControllerProvider.future)
|
||||
.timeout(const Duration(seconds: 1));
|
||||
_logger.debug("initialized [System Tray Controller]");
|
||||
} catch (error, stackTrace) {
|
||||
_logger.warning(
|
||||
"error initializing [System Tray Controller]",
|
||||
error,
|
||||
stackTrace,
|
||||
);
|
||||
}
|
||||
await _safeInit(
|
||||
"system tray",
|
||||
() => container.read(systemTrayControllerProvider.future),
|
||||
timeout: 1000,
|
||||
);
|
||||
}
|
||||
|
||||
Logger.bootstrap.info("bootstrap took [${stopWatch.elapsedMilliseconds}ms]");
|
||||
stopWatch.stop();
|
||||
|
||||
runApp(
|
||||
ProviderScope(
|
||||
parent: container,
|
||||
@@ -150,19 +163,36 @@ Future<void> _lazyBootstrap(
|
||||
if (!silentStart) FlutterNativeSplash.remove();
|
||||
}
|
||||
|
||||
void initLoggers(
|
||||
Result Function<Result>(ProviderListenable<Result>) read,
|
||||
bool debug,
|
||||
) {
|
||||
final logLevel = debug ? LogLevel.all : LogLevel.info;
|
||||
final logToFile = debug || (!Platform.isAndroid && !Platform.isIOS);
|
||||
if (logToFile) {
|
||||
_loggers.addPrinter(
|
||||
FileLogPrinter(read(logPathResolverProvider).appFile().path),
|
||||
);
|
||||
Future<T> _init<T>(
|
||||
String name,
|
||||
Future<T> Function() initializer, {
|
||||
int? timeout,
|
||||
}) async {
|
||||
final stopWatch = Stopwatch()..start();
|
||||
Future<T> func() => timeout != null
|
||||
? initializer().timeout(Duration(milliseconds: timeout))
|
||||
: initializer();
|
||||
try {
|
||||
final result = await func();
|
||||
Logger.bootstrap
|
||||
.debug("[$name] initialized in ${stopWatch.elapsedMilliseconds}ms");
|
||||
return result;
|
||||
} catch (e, stackTrace) {
|
||||
Logger.bootstrap.error("[$name] error initializing", e, stackTrace);
|
||||
rethrow;
|
||||
} finally {
|
||||
stopWatch.stop();
|
||||
}
|
||||
}
|
||||
|
||||
Future<T?> _safeInit<T>(
|
||||
String name,
|
||||
Future<T> Function() initializer, {
|
||||
int? timeout,
|
||||
}) async {
|
||||
try {
|
||||
return await _init(name, initializer, timeout: timeout);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
Loggy.initLoggy(
|
||||
logPrinter: _loggers,
|
||||
logOptions: LogOptions(logLevel),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user