exampleMain function

void exampleMain()

APPROACH 2: Manual Sentry integration (for more control) Use this if you need more control over initialization order or want to use the ErrorReporter interface pattern

IMPORTANT: This approach does NOT use appRunner, so you must:

  • Call initialize() on the reporter before runApp()
  • Set managesOwnErrorHandlers: false in ErrorReportingConfig
  • Let Dreamic's appInitErrorHandling() set up error handlers

Example Sentry implementation

To use this:

  1. Add sentry_flutter to your pubspec.yaml
  2. Uncomment the Sentry import above and the implementation below
  3. Configure in your main() function before calling appInitErrorHandling()
// pubspec.yaml
dependencies:
  sentry_flutter: ^9.7.0

Build commands with environment configuration:

# Development build
flutter build ios --dart-define=ENVIRONMENT_TYPE=development

# Staging build
flutter build ios --dart-define=ENVIRONMENT_TYPE=staging

# Production build
flutter build ios --dart-define=ENVIRONMENT_TYPE=production

Example main.dart setup

Implementation

/*
class SentryErrorReporter implements ErrorReporter {
  final String dsn;
  final String? environment;
  final String? release;

  SentryErrorReporter({
    required this.dsn,
    this.environment,
    this.release,
  });

  @override
  Future<void> initialize() async {
    // Get the app version for release tracking
    final appRelease = release ?? await AppConfigBase.getReleaseId();

    // IMPORTANT: This does NOT use appRunner
    // Error handlers are managed by Dreamic's appInitErrorHandling()
    await SentryFlutter.init(
      (options) {
        options.dsn = dsn;
        // Use ENVIRONMENT_TYPE dart-define or fallback to parameter
        options.environment = environment ?? AppConfigBase.environmentType.value;
        // Use the app version for release tracking
        options.release = appRelease;
        options.tracesSampleRate = 1.0;

        // Optional: Add custom configuration
        options.beforeSend = (event, hint) {
          // You can modify or filter events here
          return event;
        };
      },
      // DO NOT use appRunner here - error handlers managed by Dreamic
    );
  }

  @override
  void recordError(Object error, StackTrace? stackTrace) {
    Sentry.captureException(
      error,
      stackTrace: stackTrace,
    );
  }

  @override
  void recordFlutterError(FlutterErrorDetails details) {
    Sentry.captureException(
      details.exception,
      stackTrace: details.stack,
    );
  }

  // Additional helper methods for Sentry-specific features
  void setUserContext(String userId, String email, String username) {
    Sentry.configureScope((scope) {
      scope.user = SentryUser(
        id: userId,
        email: email,
        username: username,
      );
    });
  }

  void addBreadcrumb(String message, String category) {
    Sentry.addBreadcrumb(
      Breadcrumb(
        message: message,
        category: category,
        timestamp: DateTime.now(),
      ),
    );
  }

  void setTag(String key, String value) {
    Sentry.configureScope((scope) {
      scope.setTag(key, value);
    });
  }
}
*/

/// Example main.dart setup
void exampleMain() async {
  WidgetsFlutterBinding.ensureInitialized();

  // ==================================================================================
  // APPROACH 1 (RECOMMENDED): Use Sentry's appRunner wrapper
  // ==================================================================================
  // This is Sentry's recommended approach - see exampleMainSentryWrapper() above
  //
  // Summary:
  // - Use SentryFlutter.init() with appRunner parameter
  // - Sentry manages all error handlers automatically
  // - DO NOT call appInitErrorHandling()
  // - Clean and simple setup
  //
  // Example:
  /*
  await SentryFlutter.init(
    (options) {
      options.dsn = 'https://your-dsn@sentry.io/project-id';
      options.environment = AppConfigBase.environmentType.value;
      options.release = await AppConfigBase.getReleaseId();
      options.tracesSampleRate = 1.0;
    },
    appRunner: () => appRunIfValidVersion(() => MyApp()),
  );
  return; // Exit main - app is running
  */

  // ==================================================================================
  // APPROACH 2: Manual integration with Dreamic's error handling
  // ==================================================================================
  // Use this if you need more control or want to use the ErrorReporter interface

  // OPTION 1: Use Sentry only (recommended for web apps)
  /*
  // Environment and release are automatically configured
  // Environment uses ENVIRONMENT_TYPE dart-define (see AppConfigBase.environmentType)
  // Release is auto-generated from app version (see AppConfigBase.getReleaseId())
  configureErrorReporting(
    ErrorReportingConfig.customOnly(
      reporter: SentryErrorReporter(
        dsn: 'https://your-dsn@sentry.io/project-id',
        // environment and release auto-configured from AppConfigBase
      ),
      enableOnWeb: true,  // Sentry works on web
      enableInDebug: false,  // Disable in debug mode
      managesOwnErrorHandlers: false,  // We're using manual integration
    ),
  );

  // Initialize error handling with configured reporter
  await appInitErrorHandling();

  // Run your app
  runApp(MyApp());
  */

  // OPTION 2: Use both Firebase Crashlytics and Sentry
  /*
  configureErrorReporting(
    ErrorReportingConfig.both(
      reporter: SentryErrorReporter(
        dsn: 'https://your-dsn@sentry.io/project-id',
        // environment and release auto-configured from AppConfigBase
      ),
      enableOnWeb: false,  // Crashlytics doesn't work on web
      enableInDebug: false,
      customReporterManagesErrorHandlers: false,
    ),
  );

  // Initialize error handling with configured reporter
  await appInitErrorHandling();

  // Run your app
  runApp(MyApp());
  */

  // OPTION 3: Use Firebase Crashlytics only (default)
  /*
  configureErrorReporting(
    ErrorReportingConfig.firebaseOnly(
      enableInDebug: false,
      enableOnWeb: false,
    ),
  );
  // Or simply don't call configureErrorReporting() at all

  // Initialize error handling with configured reporter
  await appInitErrorHandling();

  // Continue with your app initialization...
  runApp(MyApp());
  */
}