当前教程只负责搭建Flutter模块
搭建前提
一、需要搭建Sentry服务Sentry搭建教程
二、熟悉Flutter异步异常同步异常
入坑注意事项
一、main方法中将所有初始化操作都包含在runZoned中[1.17.0版本以上推荐使用runZonedGuarded]
不包含在里面会导致runZoned[runZonedGuarded]失效(现目前测试是此原因)监听不到异常
二、区分异步异常与同步异常
具有async以及请求异常为异步异常,try/catch为同步异常
三、教程中Map对象中有\n符号,是为了在服务页面(html页面自动解析\n符号)显示容易解读
着手搭建
一、异常上报数据
1、错误标题
2、错误详细位置
3、设备信息
4、用户信息
二、用到插件
1、sentry: ">=3.0.0 <4.0.0";以官网为准Flutter官方推荐使用样例
2、device_info;获取设备信息,版本以插件库为准
三、异常分类处理
1、RangeError ;dart异常
2、FlutterErrorDetails;页面渲染异常
3、MissingPluginException; 服务异常
4、DioError ;Dio请求异常
异常都为自定义可由error.runtimeType.toString()断定为什么异常
四、异常处理
枚举定义
enum ErrorExceptionEnum{
/// dart异常
RangeError,
///页面渲染异常
FlutterErrorDetails,
///服务定义异常
MissingPluginException,
///dio请求异常
DioError
}
请求错误定义
///异常类型与枚举对应
Map<String ,ErrorExceptionEnum> errorMap = {
'RangeError' : ErrorExceptionEnum.RangeError,
'FlutterErrorDetails' : ErrorExceptionEnum.FlutterErrorDetails,
'MissingPluginException' : ErrorExceptionEnum.MissingPluginException,
'DioError' : ErrorExceptionEnum.DioError,
};
class ErrorParsing{
static dynamic errorStatus(dynamic error){
///判断是否是请求异常
///将请求接口地址获取
if(errorMap[error.runtimeType.toString()] == ErrorExceptionEnum.DioError){
return {
'\n msgData' :error?.response?.data??'',
'\n 请求域名' :error?.request?.baseUrl ??'',
'\n 请求类型' : error?.request?.method??'',
'\n 请求地址' : error?.request?.path??'',
'\n 错误error' : '$error \n'
};
}
return error;
}
}
获取设备信息
1、Android信息处理
////自己翻译结果
Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
return <String, dynamic>{
' \n 最新补丁日期':'${build.version.securityPatch}',
' \n 操作系统名' : '${build.version.baseOS??'安卓'}',
' \n sdkInt':'${build.version.sdkInt}',
'\n Android版本': '${build.version.release} ',
'\n 手机品牌 ': '${build.brand} ',
'\n 手机详细版本': '${build.model} ',
'\n 外观设计名 ': '${build.device} ',
'\n 版本号': '${build.display} ',
'\n 当前手机唯一标识': '${build.fingerprint} ',
'\n 内核(单词简写)': '${build.hardware} ',
'\n 主机名 ': '${build.host} ',
'\n id': '${build.id} ',
'\n supported32BitAbis': '${build.supported32BitAbis} ',
'\n supported64BitAbis': '${build.supported64BitAbis} ',
'\n supportedAbis': '${build.supportedAbis} ',
'\n 是否真机': '${build.isPhysicalDevice} \n',
};
}
///官方插件提供样例device_info
// Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
// return <String, dynamic>{
// 'version.securityPatch': build.version.securityPatch,
// 'version.sdkInt': build.version.sdkInt,
// 'version.release': build.version.release,
// 'version.previewSdkInt': build.version.previewSdkInt,
// 'version.incremental': build.version.incremental,
// 'version.codename': build.version.codename,
// 'version.baseOS': build.version.baseOS,
// 'board': build.board,
// 'bootloader': build.bootloader,
// 'brand': build.brand,
// 'device': build.device,
// 'display': build.display,
// 'fingerprint': build.fingerprint,
// 'hardware': build.hardware,
// 'host': build.host,
// 'id': build.id,
// 'manufacturer': build.manufacturer,
// 'model': build.model,
// 'product': build.product,
// 'supported32BitAbis': build.supported32BitAbis,
// 'supported64BitAbis': build.supported64BitAbis,
// 'supportedAbis': build.supportedAbis,
// 'tags': build.tags,
// 'type': build.type,
// 'isPhysicalDevice': build.isPhysicalDevice,
// 'androidId': build.androidId,
// 'systemFeatures': build.systemFeatures,
// };
// }
2、IOS设备信息获取
Map<String, dynamic> _readIosDeviceInfo(IosDeviceInfo data) {
return <String, dynamic>{
'\n 设备名': '${data.name} ',
'\n 操作系统名': '${data.systemName} ',
'\n 系统版本': '${data.systemVersion} ',
'\n 设备型号': '${data.model} ',
' \n 设备名(本地)': '${data.localizedModel}',
'\n 当前设备唯一值': '${data.identifierForVendor} ',
'\n 是否真机': '${data.isPhysicalDevice} ',
'\n 版本号': '${data.utsname.version} ',
'\n 硬件类型': '${data.utsname.machine} \n',
};
}
///官方插件提供样例device_info
// Map<String, dynamic> _readIosDeviceInfo(IosDeviceInfo data) {
// return <String, dynamic>{
// 'name': data.name,
// 'systemName': data.systemName,
// 'systemVersion': data.systemVersion,
// 'model': data.model,
// 'localizedModel': data.localizedModel,
// 'identifierForVendor': data.identifierForVendor,
// 'isPhysicalDevice': data.isPhysicalDevice,
// 'utsname.sysname:': data.utsname.sysname,
// 'utsname.nodename:': data.utsname.nodename,
// 'utsname.release:': data.utsname.release,
// 'utsname.version:': data.utsname.version,
// 'utsname.machine:': data.utsname.machine,
// };
// }
3、获取设备信息
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
Future<Map<String, dynamic>> initPlatformState() async {
Map<String, dynamic> deviceData;
try {
if (Platform.isAndroid) {
deviceData = _readAndroidBuildData(await deviceInfoPlugin.androidInfo);
} else if (Platform.isIOS) {
deviceData = _readIosDeviceInfo(await deviceInfoPlugin.iosInfo);
}
} on PlatformException {
deviceData = <String, dynamic>{
'Error:': 'Failed to get platform version.'
};
}
return deviceData;
}
异常数据上报(可上报到Sentry或者进行接口上报)
static Future<Null> reportError(dynamic error, dynamic stackTrace) async {
print("异常收集 error = ${error.toString()}");
print("error.type = ${error.runtimeType.toString()}");
initPlatformState().then((res){
Map<String,dynamic> _errMap = {
'\n 错误类型' :error.runtimeType.toString(),
'\n error' : ErrorParsing.errorStatus(error),
'\n 设备信息' :res,
'\n 用户信息' :'${App.currentUser.toString()} \n '
};
...Sentry上报或者接口上报
}).catchError((err){
Map<String,dynamic> _errMap = {
'\n 错误类型' :error.runtimeType.toString(),
'\n error' : ErrorParsing.errorStatus(error),
'\n 设备信息' :'获取设备信息出错',
'\n 用户信息' : '${App.currentUser.toString()} \n '
};
...Sentry上报或者接口上报
});
}
Sentry上报
import 'package:sentry/sentry.dart'
final String _dsn = 'Sentry服务模块地址';
final RcSentry.SentryClient _sentry = new RcSentry.SentryClient(dsn: _dsn);
///提交异常到Sentry服务
_sentry.captureException(
exception: _errMap,
stackTrace: stackTrace,
);
错误页面上报
定义错误友好页面
在main -> 首页中定义接收错误ErrorWidget.builder = getErrorWidget;
///捕获页面异常,建议布局分块布局,以免出现异常异常模块以下都不会显示
Widget getErrorWidget(FlutterErrorDetails error) {
print(
"异常日志开始+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
print("异常日志=$error");
print(
"异常日志结束--------------------------------------------------------------------");
///传入错误自动上传
reportError(error, null);
return Scaffold(
body: Center(
child: Text('错误页面')),
);
}
同步异常上报
try{
...
}catch(err,stack){
reportError(err, stack);
}
异步异常上报
只需要在方法上添加async可自行获取异常
个人github博客转载18487115313.github.io
网友评论