TingYun_App_Flutter
环境要求
- Dart Version: >= 2.4.0
- Flutter Version >= 1.12.0
嵌码步骤
Flutter 嵌码分为两个部分「原生项目嵌码」和「Flutter插件嵌码」
1、原生项目嵌码
请确保嵌码 APP 原生部分已集成 TingYun_SDK ,如未集成可参照原生项目部署文档完成嵌码
-
Android 部署文档
-
iOS 部署文档
由于「Flutter插件嵌码」会通过 pod install 引入 iOS SDK,所以请从
添加 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()); }
若您的应用在 runApp() 前调用了 WidgetsFlutterBinding.ensureInitialized(),SDK 将无法采集到 Zone 的 error,您可以在外部添加 runZonedGuarded 捕获
import 'package:tingyun_flutter_plugin/tingyun_flutter_plugin.dart';
void main() {
// runApp(MyApp());
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
Tingyun().start(MyApp(),
);
}, (Object error, StackTrace stack) {
if(error != null && stack != null){
Tingyun().reportError(error.toString(), stack.toString());// 捕获后可以传给 Tingyun SDK
}
});
}
-
运行日志
运行项目工程后控制台会显示以下日志:
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. 可以通过网络埋点接口获取包含读流的响应时间 |
崩溃/卡顿/error | 1. 崩溃 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. 首次/冷启动耗时默认只计算初始化到第一页面加载结束;可以调用接口自定义启动结束点,具体见部署文档「自定义启动结束点」 |
|
操作体验 | 自定义Action | 1. 自定义Action耗时 2. 事件性能数据:网络「Android」 3. 设备附加信息 |
不支持自动采集操作体验数据 | 1. 可以通过自定义Action来定义一个操作来获取性能耗时 |
页面体验 | 不支持页面体验数据采集 | 1. 可以通过自定义Action来定义一个页面获取性能耗时 | ||
拨测模块 | 1. TCPPing 2. ICMPPIng 3. 单文件下载 4. MTR |
1. ping耗时 2. 丢包率 3. CDN厂商 4. 单文件下载耗时 |
单文件下载不支持使用自签名证书的HTTPS文件下载 |