TingYun_App_Flutter

环境要求

  • Dart Version: >= 2.4.0
  • Flutter Version >= 1.12.0

嵌码步骤

Flutter 嵌码分为两个部分「原生项目嵌码」和「Flutter插件嵌码」

1、原生项目嵌码

请确保嵌码 APP 原生部分已集成 TingYun_SDK ,如未集成可参照原生项目部署文档完成嵌码

2、Flutter 插件嵌码

2.1、添加依赖

  • 添加依赖

    在项目的「pubspec.yaml」文件中添加「TingYun Flutter」插件,目前支持【远程依赖】及【本地依赖】两种部署方式

    • 远程依赖
      dependencies:
          tingyun_flutter_plugin: ^1.0.0 
      
    • 本地依赖
      dependencies:
          tingyun_flutter_plugin:
              path: tingyun_flutter_plugin //tingyun_flutter_plugin 需替换为本地 TingYun flutter 插件的目录
      
  • 获取插件
    • 添加后需要在项目「根目录下」执行 flutter packages get 命令

    • 注意:iOS 添加依赖需在项目 ios 目录下执行pod install

2.2、Flutter 插件初始化

  • 替换 runApp()

    需注释原有的runApp()方法,并添加Tingyun().start(MyApp()方法

    import 'package:tingyun_flutter_plugin/tingyun_flutter_plugin.dart';
    
    void main() {
      // runApp(MyApp());
        Tingyun().start(MyApp());
    }
    
  • 运行日志

    运行项目工程后控制台会显示以下日志:

    tingyun flutter impl start
    get configure from tingyun:xxx //xxx 为从 native 端 SDK 获取到的功能开关配置情况
    //初始化成功时候显示
    tingyun flutter plugin success!
    //初始化失败时显示
    tingyun flutter plugin failed to initialize. Error: xxx //xxx 为错误描述
    

2.3、兼容异常数据

由于 Flutter 只允许单一 handler 收集 error 数据,听云提供了相关参数以便兼容 App 自身采集 error 的场景
  • 控制参数

    我们在tingyun_flutter_plugin初始化方法中提供了两个参数,您可以选择传入相关函数来处理 error

    /**
    因为flutter error 的捕获机制原因,需要提供2个不同的函数来进行处理,
    onError 是flutter框架没有捕获到的异常的时候,通过runZoned来捕获的error的回调函数
    flutterOnError 是flutter框架通过Flutter.onError来捕获异常的回调函数
    
    @onError: 需要传入原型为 void FunctiononError(Object, StackTrace)的函数, 
    @flutterOnError: 需要传入原型为 void FunctionFlutterError(FlutterErrorDetails details)的函数
    */
    Tingyun().start(MyApp(), {Function onError, Function flutterOnError});
    
  • 代码示例
    void main() => Tingyun().start(MyApp(),onError: onCustomError, flutterOnError: onCustomFlutterError);
    
    void onCustomError(Object object, BuildContext stackTrace){
      print('onCustomError happened');
    }
    
    void onCustomFlutterError(FlutterErrorDetails details){
      print('onCustomFlutterError happened');
    }
    

3、Android WebView 数据采集

由于操作系统差异,TIngYun_iOS_SDK 默认支持自动采集 WebView 数据,Android 则需按以下步骤添加相关设置

  • 设置 WebChromeClient
    • Android 采集 WebView 数据需要设置 WebChromeClient,并在 onProgressChanged() 中调用 TingYun_Android_SDK 提供的 initJSMonitor() 方法
  • 举例

    以【 webview_flutter-0.3.24】为例

    • 打开 webview_flutter-0.3.24 android 目录下的 build.gradle 文件并添加 TingYun_Android_SDK 依赖

      dependencies {
          compileOnly "com.networkbench:tingyun-ea-agent-android:2.15.5"   
      }
      
    • 在 WebChromeClient 中重写 onProgressChanged(),并添加 TingYun_SDK 的 initJSMonitor() 方法

      private class FlutterWebChromeClient extends WebChromeClient {
      
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
          try {
            Class.forName("com.networkbench.agent.impl.instrumentation.NBSWebChromeClient");
            com.networkbench.agent.impl.instrumentation.NBSWebChromeClient.initJSMonitor(view, newProgress);
          } catch (ClassNotFoundException e) {
            e.printStackTrace();
          }
          super.onProgressChanged(view, newProgress);
        }
        ... ...
      }
      

API接口

1、自定义网络请求

TingYun_SDK 通过设置 HttpOverrides.global 自动采集网络数据,目前支持「httpClient」以及基于HttpClient 封装的「dio、http」等网络库。

若您的项目设置了 HttpOverrides,将会导致 TingYun_SDK 无法采集网络数据,需要手动埋点采集数据。

  • 相关接口

/*
@url:网络请求的完整 url
*/
TYWebRequestTiming timing = await Tingyun().createWebRequest(String url);// 创建一条网络性能数据
timing.start();// 请求开始
/*
@code:请求的状态码
*/
timing.stop(int code);// 请求结束
  • 代码示例

var url = "https://www.tingyun.com";
TYWebRequestTiming timing = await Tingyun().createWebRequest(url);
timing.startWebRequestTiming();
var response = await http.get(url)
        .then((response) {
    timing.stop(response.statusCode);// 请求结束
    return response;
 });

2、自定义启动结束点

TingYun_SDK 默认计算 SDK 初始化开始至第一个页面加载结束的时间为「冷启动耗时」,研发人员可以根据自身应用需求更改计算「冷启动耗时」的结束点。

  • 项目要求

    • Android 项目
      • 采集冷启动(含首次启动)数据需实现自定义的 Application 类
    • iOS 项目
      • 采集启动数据需要在 main 函数中嵌码
  • 开启自定义启动开关

    需在 native 部分初始化 TingYun_SDK 时调用相关接口

    • Android 接口
      /*
      @isCustom:是否启用自定义启动,默认 false,如需开启,置为 true
      */
      NBSAppAgent.isCustomAppStart(boolean isCustom);
      
    • iOS 接口
      /**
       是否启用自定义启动,在启动SDK之前调用,默认 NO,如需开启,置为 YES
       */
      + (void)customLanuchEnd:(BOOL)enable;
      
    • 代码示例
      • Android 示例
      public class MyApplication extends Application {
          @Override
          public void onCreate() {  
          NBSAppAgent.setLicenseKey("AppKey")
          .isCustomAppStart(true)//在初始化SDK时调用,开启自定义启动时间功能
          .start(this.getApplicationContext());
          }
      }
      
      • iOS 示例
      int main(int argc, char* argv[]) {
        @autoreleasepool {
                [NBSAppAgent customLanuchEnd:YES];
                [NBSAppAgent setRedirectURL:@"Dc_Redirect"];
                [NBSAppAgent startWithAppID:@"AppKey"];
          return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
      }
      
  • 设置自定义启动的结束点

    需要开启「自定义启动开关」,当自定义启动开关设置为 true 时,自定义启动结束点的接口设置才会生效

    • 相关接口
      Tingyun().setCustomOnResumeEndIns();
      
    • 代码示例
       Widget build(BuildContext context) {
          Tingyun().setCustomOnResumeEndIns();
          return Scaffold(
            body:Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              .....
           ));
       }
      

3、自定义用户操作

支持通过埋点方式采集操作数据,可支持 root 和 sub 两层 trace(注意:这里两层是指 sub trace 允许有多个并非两个)。

  • 接口限制

    • 操作数据截至到 root 节点结束
    • 多组埋点 root 节点不能交叉调用
  • 相关接口

/*
@name:操作名称
*/
TingyunRootAction rootAction = Tingyun().enterAction(String name);//创建一个操作
/*
@name:子 Action 名称
*/
TingyunAction subAction = rootAction.enterAction(String name);//创建一个子 Action
subAction.leaveAction();//子 Action 完成
/*
@props:附加信息
@tag:tag 标识
*/
rootAction.leaveAction({Map<String, dynamic> props, String tag = ""});//操作完成
  • 代码示例

TingyunRootAction rootAction = Tingyun().enterAction('my button enter');

TingyunAction subAction1 = rootAction.enterAction('sub1 button enter');

subAction1.leaveAction();

TingyunAction subAction2 = rootAction.enterAction('sub2 button enter');

subAction2.leaveAction();

rootAction.leaveAction(props:{"key1":"value1","key2":"value2"},tag: "tag");

4、自定义错误

使用「自定义错误」接口可以采集研发人员「try / catch 异常」和「业务错误」并在听云平台「异常分析」→「错误」中进行展示,可以帮助研发人员收集异常和错误。

  • 相关接口

/*
 @message:不可以传空,最大长度 1024 字节,超出截取前 1024 字节
 @stackTrace:上传 exception 取到抛出时的堆栈
 @props:value 值支持 Number, String, Array, Map 类型,最大限制128k,若超出最大限制上传为空
 */
Tingyun().reportError(String message, String stackTrace, {Map<String, dynamic> props});
  • 代码示例

try {
    throw new StateError('This is an async Dart exception.');
} catch (exception, stack) {
    Tingyun().reportError(exception.toString(), stack.toString(),props: {"ke y1":"value1","key2":"value2"});
}  

5、设置用户标识

通过添加「用户标识」可在听云报表平台通过该标识检索到具体用户的性能问题

  • 相关接口

/*
@userIdentifier:最多包含64个字符,超出截取前64字符,支持中文、英文、数字、下划线,但不能包含空格或其他的转义字符
*/
Tingyun().setUserIdentifier(String userIdentifier);
  • 代码示例

Tingyun().setUserIdentifier("zhangsan@tingyun.com");

6、记录用户路径(面包屑)

研发人员可以在应用程序的任意位置调用「面包屑」接口进行埋点。当应用程序发生崩溃时,SDK 会按代码的触发顺序收集埋点信息并在崩溃轨迹中高亮显示,以协助研发人员在应用崩溃时了解代码调用逻辑。

  • 相关接口

/*
  @breadcrumb:自定义信息,最多包含100个字符,超出截取前100字符,支持中文、英文、数字、下划线
*/
Tingyun().leaveBreadcrumb(String breadcrumb);
  • 代码示例

Tingyun().leaveBreadcrumb("添加购物车");

7、自定义附加信息

在应用发生崩溃的时候,研发人员往往需要更多的信息以收集现场环境,可以通过调用「自定义崩溃附加信息」接口上传额外信息,协助分析崩溃问题。

  • 相关接口

/*
只保留最新的10条数据,随崩溃上传
@key:key 值
@value:value 值,最大长度限制100,超出则截取前100
*/
Tingyun().setUserCrashMessage(String key, String value);
  • 代码示例

Tingyun().setUserCrashMessage("当前页面", "Main");

功能支持列表

模块支持类性采集数据不支持类型备注
网络模块1. dio
2. http
3. httpclient
1. 响应时间
2. DNS时间
3. 首包时间(响应时间-DNS时间)
1. 建联时间
2. SSL时间
3. 剩余包时间
4. 客户端时间
5. 传输字节数
6. 网络错误
1. 响应时间不包含读流时间
2. 可以通过网络埋点接口获取包含读流的响应时间
崩溃/卡顿/error1. 崩溃
2. Flutter error
1. 崩溃/error堆栈
2. 崩溃/error轨迹
3.设备附加信息
4.用户自定义信息
5.面包屑
不支持卡顿采集由于 Flutter 只能单一 handler 采集 error 数据,所以为了兼容 App 自身 error 处理,可以在听云Flutter初始化方法中传入自身error处理方法来处理相关 error,具体见部署文档「初始化补充说明」
webview模块1. WKWebview数据获取「iOS」
2. 原生webview和腾讯X5「Android」
1. 主页面网络性能数据,如页面加载时间,白屏时间,首屏时间,可交互时间
2. 页面资源性能数据
3. js错误统计
1. 不支持WKWebview网络数据获取「iOS」
2. 不支持UIWebview页面性能数据「iOS」
1. 通过注入听云Web探针获取webview性能数据
2. 由于苹果要求iOS已不在采集UIWebview页面性能数据
3. Android不支持自动采集webview数据,需要在对应flutter webview plugin中添加initJSMonitor()方法,具体见部署文档「WebView 数据采集」
启动体验1. 首次启动
2. 冷启动
3. 热启动
1. 启动耗时
2. 启动次数
3. 启动期间的崩溃
4. 事件性能数据:网络、数据库、image、json、Storage、用户自定义函数
5. 设备附加信息
1. 以下情况采集不到启动数据:
iOS:
1). 不在main函数嵌码
2). rootVC是UIViewController
3). 启动过程中被权限弹窗打断
Android:
1). 没有使用自定义application类
2. 首次/冷启动耗时默认只计算初始化到第一页面加载结束;可以调用接口自定义启动结束点,具体见部署文档「自定义启动结束点」
操作体验自定义Action1. 自定义Action耗时
2. 事件性能数据:网络「Android」
3. 设备附加信息
不支持自动采集操作体验数据1. 可以通过自定义Action来定义一个操作来获取性能耗时
页面体验不支持页面体验数据采集1. 可以通过自定义Action来定义一个页面获取性能耗时
拨测模块1. TCPPing
2. ICMPPIng
3. 单文件下载
4. MTR
1. ping耗时
2. 丢包率
3. CDN厂商
4. 单文件下载耗时
单文件下载不支持使用自签名证书的HTTPS文件下载

Libraries

tingyun_flutter_plugin