Flutter-使用Sentry上报异常搭建

当前教程只负责搭建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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353