In this class, a general Flutter exception reporting module will be implemented to provide reporting and monitoring security for online operations. Secondly, the Sentry platform will be used to implement exception alarm and management functions. Let’s first take a look at what the online security of the App includes.
Online security operations
When launching each client version, we must have a crash standard. Since the client cannot be rolled back after it is released, data needs to be used to assist judgment when publishing. Here we need to use the crash rate to assist in judging whether it is necessary. Further grayscale more users. To do this, you need to report abnormal client error reports to the platform. Both Android and iOS have similar functional modules. The corresponding theoretical methods are also introduced on the Flutter official website . You can go to the official website to learn more. The purpose of writing this column is to use this function as a common module and practice the process.
Next, let's take a look at how to use the theoretical knowledge of the official website to encapsulate this function into a general exception reporting module.
Universal reporting module
According to the documentation on the official website, we divide the process into three steps:
-
Modify the main function in main.dart;
-
Exception catching;
-
Capture content reporting.
Next, we will look at the implementation principles of the three processes respectively.
Step 1: Modify the main function in main.dart
In the main function of our previous project code logic, the following code method is used to start and run the Flutter project.
/// App 核心入口文件
void main() {
runApp(MyApp());
}
Since we need to catch exceptions, we put the runApp execution into the exception capture module and modify it as follows.
import 'package:two_you_friend/util/tools/app_sentry.dart';
/// App 核心入口文件
void main() {
AppSentry.runWithCatchError(MyApp());
}
A general exception capture module is introduced here. You can also use this module directly to implement reporting in your project later. Next, let's take a look at the exception capture logic implemented by AppSentry.
Step 2: Exception catching
The implementation of this function will apply to two knowledge points: FlutterError and runZonedGuarded.
In Flutter, FlutterError can be used to capture errors during runtime, including during construction, layout and drawing.
runZonedGuarded uses Zone.fork to create a new area to run the code logic, that is, runApp. When an error is encountered, its callback function onError will be executed. Secondly, if Zone.current.handleUncaughtError is used in the project, the error will also be thrown. Execute onError logic, let's look at the code specifically, as follows:
/// catch 组件异常
///
/// 开发模式下,本地打印,上线时则调用 sentry 平台
static void runWithCatchError(Widget appMain) {
// 捕获并上报 Flutter 异常
FlutterError.onError = (FlutterErrorDetails details) async {
if (!inProduction) {
FlutterError.dumpErrorToConsole(details);
} else {
Zone.current.handleUncaughtError(details.exception, details.stack);
}
};
runZonedGuarded<Future<Null>>(() async {
runApp(appMain);
}, (error, stackTrace) async {
await _reportError(error, stackTrace);
});
}
FlutterError.onError is used to catch exceptions. It will be judged whether it is in a formal environment. If so, the error log will be printed locally. If not, the runZonedGuarded onError logic will be executed. RunApp is executed in the runZonedGuarded code. When an exception is encountered, _reportError is called to implement error reporting. Next, let's take a look at the implementation part of _reportError.
Step 3: Report exceptions
The specific exception information of the client has been obtained above. Next, we use the Sentry platform to report the exception information. Before applying the Sentry platform, you need to apply for access. The specific access method is introduced in "Sentry Platform" in this lesson. After successfully accessing the Sentry platform, a dsn will be provided. Here we need to configure it in the file, as shown in the following code. Because Sentry is a third-party library, you need to add library dependencies to pubspec.yaml and update the local library.
/// 创建 SentryClient 用于将异常日志上报给 sentry 平台
final SentryClient _sentry = SentryClient(
dsn: 'https://[email protected]/5362342',
);
/// 判断当前环境类型
const bool inProduction = bool.fromEnvironment("dart.vm.product");
_sentry is the reporting handle created using the Sentry third-party library, and dsn is the reporting identifier for our test. Please apply for it yourself when testing, otherwise you will not be able to see your own exception reporting content. In the above code, inProduction is the logic used to obtain whether it is a formal environment. Next, let’s take a look at the reporting logic. The code is as follows:
/// 上报异常的函数
static Future<void> _reportError(dynamic error, dynamic stackTrace) async {
if (!inProduction) { // 判断是否为正式环境
print(stackTrace);
}
// sentry 上报
final SentryResponse response = await _sentry.captureException(
exception: error,
stackTrace: stackTrace,
);
if (response.isSuccessful) {
print('Success! Event ID: ${response.eventId}');
} else {
print('Failed to report to Sentry.io: ${response.error}');
}
}
First, determine whether it is a formal environment. If not, print it directly. You can also use the following code to print local logs. If it is a formal environment, use _sentry.captureException to report the exception, and finally print whether the execution is successful. The latter paragraph can be removed, mainly for viewing during real machine debugging.
FlutterError.dumpErrorToConsole(FlutterErrorDetails(exception: error));
The above completes the code of the universal reporting tool. Next, we will teach you how to register Sentry and create a project to obtain a dsn.
Sentry Platform
Let’s take a look at the specific creation steps:
1. Create a registered account and go to the official website . Please fill in the details according to your own information. After the registration is completed, log in directly;
2. Create a project. If there are no groups in this process, you will be asked to fill in the groups. Just fill in the groups as required;
3. Report for testing. There will be examples of various SDKs, but there is no Flutter. You can ignore it and enter the project or personal page directly. You can see the interface as shown in Figure 1.
Figure 1 Sentry Platform
4. Follow the method in Figure 2 to see the dsn we need. If it is newly registered, you can click Setup Sentry in Figure 2 to quickly find it;
Figure 2 dsn query guide
5. Replace the dsn in the project code.
After the above 5 steps, the project access can be completed. Next, we will verify whether the report is normal.
Report test
In order to verify this function, we need to specifically modify the normal code to make it abnormal. Here we modify the code in the "Image Flow" menu on the left as follows:
Widget build(BuildContext context) {
if (contentList == null) { // 判断是否为空
return Loading();
}
List<StructContentDetail> tmpList = [];
return ListView.separated(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: contentList.length + 1, // 增加异常
......
The above is only part of the code in pages/home_page/img_flow.dart. Line 10 of the code adds an exception. Since the array length exceeds the limit, this will cause an array boundary exception to be thrown in ListView.separated. Please note that this exception catching logic will only take effect in release mode, so you need to formally build the app. Using the knowledge from the previous lesson, we will build the App as an apk file and then install it on the Android phone.
After successful installation, open the App and select "Image Stream" from the left menu. At this time, you will see an exception in the interface. After about 1-2 minutes, we go to the Sentry platform and select our creation project. You will see Figure 3 below. content to be reported.
Figure 3 Sentry exception example
Click on the specific report content to see the detailed error information. The error file and specific function have been described, and the call stack has been printed. You can view the specific error file img_flow.dart and the specific error content RangeError in the prompt message. Through the file and error details, you can easily locate the specific problem.
The above is the tool module for exception reporting. In this way, we can quickly collect and solve problems. Since main.dart has been optimized in this lesson, the reconstruction part is also introduced here.
AppProvider
In order to lighten the code in main.dart and make it more streamlined, we moved the logic of the Provider part into a new tool module, which is located in util/tools/app_provider. In main.dart, the original _getProviders method inside the function was changed to calling the getProviders method in AppProvider. The main.dart code is as follows:
/// App 核心入口文件
void main() {
AppSentry.runWithCatchError(MyApp());
}
/// MyApp 核心入口界面
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return FutureBuilder<Widget>(
future: AppProvider.getProviders(
context,
MaterialApp(
title: 'Two You', // APP 名字
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue, // App 主题
),
routes: Router().registerRouter(),
home: Entrance()),
),
builder: (BuildContext context, AsyncSnapshot<Widget> snapshot) {
if (snapshot.error != null) {
return Container(
child: CommonError(),
);
}
return Container(
child: snapshot.data,
);
});
}
}
The code is very streamlined. The calling method is modified in line 12 of the code, and component exception handling is added in line 23. The getProviders method in AppProvider is the logic of the original homepage, which is basically unchanged. You can check it out by yourself in the github source code .
Summarize
This lesson focuses on the implementation method of the general reporting module, and also introduces the application of the Sentry platform in practice. Finally, it briefly introduces the reconstruction logic in main.dart. After completing this course, you will need to master Flutter exception capture and processing methods, and be able to use the Sentry platform to assist in analyzing exception problems.
In the next lesson we will move to the next stage and we will continue to improve the functionality on the Two You App.