Ensuring the stability and performance of a Flutter app in production requires diligent monitoring. Logging and error reporting services are crucial for identifying and resolving issues that arise after deployment. By integrating these services, developers can gain valuable insights into app behavior, track crashes, and address performance bottlenecks promptly.
Why Use Logging and Error Reporting Services?
- Proactive Issue Detection: Identifies issues before they impact a large number of users.
- Comprehensive Insights: Provides detailed logs and crash reports to diagnose problems effectively.
- Improved Stability: Enhances app reliability by addressing and resolving production issues.
- Performance Monitoring: Tracks performance metrics to identify areas for optimization.
Popular Logging and Error Reporting Services for Flutter
- Firebase Crashlytics: A robust, free crash reporting solution by Google.
- Sentry: A comprehensive error tracking and performance monitoring platform.
- Bugsnag: An advanced error monitoring and crash reporting service.
- Instabug: A user-friendly platform that includes bug reporting, crash reporting, and in-app feedback.
Implementing Firebase Crashlytics in Flutter
Firebase Crashlytics is a popular choice due to its ease of integration and comprehensive features.
Step 1: Set Up Firebase Project
Create a new project in the Firebase console or use an existing one.
Step 2: Add Firebase to Your Flutter App
Install the required FlutterFire packages:
dependencies:
firebase_core: ^2.15.0
firebase_crashlytics: ^3.3.5
Then, initialize Firebase in your main.dart file:
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// Pass all uncaught errors from the framework to Crashlytics.
FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Crashlytics Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// Simulate a crash
FirebaseCrashlytics.instance.crash();
},
child: Text('Simulate Crash'),
),
),
),
);
}
}
To ensure Crashlytics is initialized correctly, you may also need to configure it in your native Android and iOS projects as described in the Firebase documentation.
Step 3: Configure Native Platforms
Android Configuration
- Enable Crashlytics in your Firebase console.
- Add the Crashlytics plugin to your project-level
build.gradle:
buildscript {
dependencies {
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9'
}
}
apply plugin: 'com.google.firebase.crashlytics'
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.8.0')
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-crashlytics'
}
iOS Configuration
- Download the
GoogleService-Info.plistfile from the Firebase console and add it to your Xcode project. - Add a Run Script phase to your Xcode build process as outlined in the Firebase documentation to upload debug symbols.
Step 4: Log Custom Events and Errors
Use the Firebase Crashlytics API to log custom events, exceptions, and user information:
FirebaseCrashlytics.instance.log('This is a custom log message.');
try {
// Some code that might throw an exception
throw Exception('An example exception');
} catch (e, stack) {
FirebaseCrashlytics.instance.recordError(e, stack, reason: 'An example exception');
}
FirebaseCrashlytics.instance.setUserIdentifier('12345');
FirebaseCrashlytics.instance.setCustomKey('string_key', 'stringValue');
FirebaseCrashlytics.instance.setCustomKey('int_key', 123);
FirebaseCrashlytics.instance.setCustomKey('double_key', 123.45);
FirebaseCrashlytics.instance.setCustomKey('bool_key', true);
Implementing Sentry in Flutter
Sentry offers more advanced features, including performance monitoring and detailed error tracking.
Step 1: Sign Up for Sentry
Create an account on Sentry.io and create a new project.
Step 2: Install Sentry Flutter Package
Add the sentry_flutter package to your pubspec.yaml:
dependencies:
sentry_flutter: ^7.10.0
Step 3: Initialize Sentry
Initialize Sentry in your main.dart file:
import 'package:flutter/widgets.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
void main() async {
await SentryFlutter.init(
(options) {
options.dsn = 'YOUR_SENTRY_DSN';
options.tracesSampleRate = 0.2;
},
appRunner: () => runApp(MyApp()),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return WidgetsApp(
builder: (context, widget) {
return SentryScreenshotWidget(child: widget!);
},
color: const Color.fromRGBO(0, 0, 0, 0),
);
}
}
Step 4: Capture Exceptions and Messages
Use Sentry’s API to capture exceptions, messages, and breadcrumbs:
try {
// Some code that might throw an exception
throw Exception('An example exception');
} catch (e, stackTrace) {
await Sentry.captureException(
e,
stackTrace: stackTrace,
);
}
Sentry.captureMessage('This is a message', level: SentryLevel.info);
Sentry.addBreadcrumb(
Breadcrumb(
message: 'Added a breadcrumb',
level: SentryLevel.info,
),
);
Logging with the logger Package
For general logging, consider using the logger package, which provides a simple and customizable way to log messages at different levels.
Step 1: Add logger Dependency
dependencies:
logger: ^1.7.1
Step 2: Use the Logger
import 'package:logger/logger.dart';
final logger = Logger();
void main() {
logger.d('Debug log');
logger.i('Info log');
logger.w('Warning log');
logger.e('Error log');
logger.wtf('WTF log');
}
Conclusion
Using logging and error reporting services is essential for maintaining a stable and performant Flutter app in production. Services like Firebase Crashlytics and Sentry offer robust features for tracking crashes, logging custom events, and monitoring app performance. By integrating these tools, developers can proactively identify and resolve issues, leading to a better user experience. Whether it’s simple logging with the logger package or comprehensive error tracking with Sentry, incorporating these practices into your Flutter development workflow is highly recommended.