main function

Future<void> main()

Entry point of this application.

Implementation

Future<void> main() async {
  await runZonedGuarded(
    () async {
      final Stopwatch watch = Stopwatch()..start();

      await Config.init();

      me.Log.options = me.LogOptions(
        level: Config.logLevel,

        // Browsers collect timestamps for log themselves.
        timeStamp: !PlatformUtils.isWeb,
        dateStamp: !PlatformUtils.isWeb,
      );

      Log.maxLogs = Config.logAmount;

      // No need to initialize the Sentry if no DSN is provided, otherwise
      // useless messages are printed to the console every time the application
      // starts.
      if (Config.sentryDsn.isEmpty || kDebugMode) {
        return _runApp();
      }

      await SentryFlutter.init((options) {
        options.dsn = Config.sentryDsn;
        options.tracesSampleRate = 1.0;
        options.sampleRate = 1.0;
        options.release = '${Pubspec.name}@${Pubspec.ref}';
        options.diagnosticLevel = SentryLevel.info;
        options.enablePrintBreadcrumbs = true;
        options.maxBreadcrumbs = 512;
        options.enableTimeToFullDisplayTracing = true;
        options.enableAppHangTracking = true;
        options.enableLogs = true;
        options.beforeSend = (SentryEvent event, Hint? hint) {
          // Modules are meaningless in Flutter.
          event.modules = {};

          final SentryException? sentryException =
              event.exceptions?.firstOrNull;
          final dynamic exception = sentryException?.throwable;

          // Connection related exceptions shouldn't be logged.
          if (exception is Exception && exception.isNetworkRelated) {
            final Exception unreachable = UnreachableException();

            return SentryEvent(
              eventId: event.eventId,
              timestamp: event.timestamp,
              modules: event.modules,
              tags: event.tags,
              fingerprint: event.fingerprint,
              breadcrumbs: event.breadcrumbs,
              exceptions: [
                SentryException(
                  type: 'UnreachableException',
                  value: unreachable.toString(),
                  stackTrace: sentryException?.stackTrace,
                  mechanism: sentryException?.mechanism,
                  throwable: unreachable,
                ),
              ],
              threads: event.threads,
              sdk: event.sdk,
              platform: event.platform,
              logger: event.logger,
              serverName: event.serverName,
              release: event.release,
              dist: event.dist,
              environment: event.environment,
              message: event.message,
              transaction: event.transaction,
              throwable: event.throwable,
              level: event.level,
              culprit: event.culprit,
              user: event.user,
              contexts: event.contexts,
              request: event.request,
              debugMeta: event.debugMeta,
              type: event.type,
            );
          }

          // [Backoff] related exceptions shouldn't be logged.
          if (exception is OperationCanceledException ||
              exception.toString() == 'Data is not loaded') {
            return null;
          }

          return event;
        };
      });

      // Transaction indicating Flutter engine has rasterized the first frame.
      final ISentrySpan ready = Sentry.startTransaction(
        'ui.app.ready',
        'ui',
        autoFinishAfter: const Duration(minutes: 2),
        startTimestamp: DateTime.now().subtract(watch.elapsed),
      )..startChild('ready');

      WidgetsBinding.instance.waitUntilFirstFrameRasterized.then(
        (_) => ready.finish(),
      );

      await _runApp();
    },
    (error, stackTrace) {
      // If Sentry is enabled, then report the exception.
      if (Config.sentryDsn.isNotEmpty && !kDebugMode) {
        WebUtils.consoleError(
          'Uncaught (in promise) DartError: $error\n'
          '${stackTrace.toString().split('\n').where((e) => e.isNotEmpty).map((e) => '    at $e\n').join()}',
        );

        Sentry.captureException(error, stackTrace: stackTrace);
      }
      // Otherwise rethrow the exception to the parent `Zone`.
      else {
        Zone.root.handleUncaughtError(error, stackTrace);
      }
    },
  );
}