Quick Tracking 性能体验SDK Flutter插件集成说明
应用性能稳定是良好用户体验中非常关键的一环,Quick Tracking 性能体验SDK Flutter插件通过轻量级的集成接入即可拥有实时、可靠、全面的应用页面性能、页面帧率、dart异常、自定义异常等监控能力,帮助开发者高效还原异常、卡顿用户的访问路径和业务现场。
1. 环境准备
Android:APM性能SDK,v2.0.0版本及以上,在工程App对应build.gradle配置脚本dependencies段中添加组件库依赖:
api 'com.lydaas.qtsdk:apm-efs:2.0.0'
iOS:APM性能SDK v2.0.0版本及以上,在项目根目录的Podfile中添加:
pod 'UMEFS_P', '2.0.0'
Flutter Common 版本,在工程pubspec.yaml中加入 dependencies:
qt_common_sdk: ^2.0.0
Flutter APM 版本,在工程pubspec.yaml中加入 dependencies:
qt_apm_sdk: ^2.3.0
版本依赖关系
qt_common_sdk: ^2.0.3:
|---依赖原生iOS 1.5.2.PX 版本
|---依赖原生 Android 1.6.1.PX 版本
qt_apm_sdk: ^2.3.0:
|---依赖原生 iOS
|-------UMAPM_P: 1.5.7.guomi
| -------UMEFS_P: 2.0.0
|---依赖原生 Android
|-------apm-crash:1.5.2.1.0.0.3_guomi
| -------apm-efs:2.0.0
Appkey获取
在初始化SDK时,需要填写参数Appkey。Appkey是在Quick Tracking中代表应用的唯一ID,在创建应用时生成,其获取或查看方法详见文档:应用管理。
收数域名获取
在“管理控制台-采集信息”模块中获取
2. 集成 Flutter APM 插件
性能体验SDK依赖统计分析SDK,您可以集成 flutter版本的统计分析,也可以集成Native版本的统计分析SDK。Flutter APM 和 Flutter Common SDK内部已集成了Android和iOS SDK,如果工程类型是Flutter App可以只集成Flutter SDK
flutter统计SDK集成方式请参考文档:qt_common_sdk
iOS统计分析SDK集成方式请参考文档:iOS SDK
Android统计分析SDK集成方式请参考文档:Android SDK
请注意:
集成Flutter SDK(已内置原生APM和Common SDK依赖)不需要在原生项目中引入原生SDK,如果您的原生项目中的Cocoapods或手动集成依赖库内存在Quick Tracking SDK依赖(原生QTCommon、原生APM),需要删掉,否则可能会导致SDK冲突。
集成步骤
在工程pubspec.yaml中加入 dependencies
# 线上依赖
dependencies:
qt_common_sdk: ^2.0.0 //统计分析
qt_apm_sdk: ^2.3.0 //性能体验
注意: 如果需要兼容flutter2.8.1的版本,可以集成qt_apm_sdk: ^2.3.0-flutter-2.8.1
导入
import 'package:qt_apm_sdk/qt_apm_sdk.dart';
2.1 实例化设置
final QuickTrackingFlutterApmSdk qtApmSdk = QuickTrackingFlutterApmSdk(
name: '',
bver: '',
flutterVersion: '您使用的flutter版本',
engineVersion: '您使用的flutter引擎版本',
enableLog: true,
enableTrackingPageFps: true,
enableTrackingPagePerf: true,
errorFilter: {
"mode": "ignore",
"rules": [],
},
trackDomain: "您的收数服务域名",
initFlutterBinding: MyApmWidgetsFlutterBinding.ensureInitialized,
// onError: (exception, stack) {},
);
参数说明:
字段 | 含义 | 是否必填 | 类型 |
name | 应用或模块名称 | 是 | string |
bver | 应用或模块版本+构建号 | 是 | string |
flutterVersion | Flutter SDK 版本(默认为空) | 否 | string |
engineVersion | flutter引擎版本 | 否 | string |
enableLog | 是否开启SDK日志打印 (默认关闭) | 否 | boolean |
enableTrackingPageFps | 开启监测页面帧率(默认关闭) | 否 | boolean |
enableTrackingPagePerf | 开启监测页面性能(默认关闭) | 否 | boolean |
errorFilter | 设置采集的异常黑白名单 | 否 | map |
trackDomain | 收数域名 | 是 | string |
initFlutterBinding | ApmWidgetsFlutterBinding的覆写和初始化方法 | 否 | function |
onError | 抛出异常回调 | 否 | function |
2.2 初始化SDK
确保去掉原有的WidgetsFlutterBinding.ensureInitialized() ,以免出现重复初始化绑定的异常造成无法正常初始化
SDK内部已通过initFlutterBinding入参带入继承的WidgetsFlutterBinding实现初始化操作
依赖ensureInitialized()初始化的代码可在此调用
需要异步获取设置应用名称和版本号可在此回调中操作
SDK实例化的设置可先将name和bver 为 "",然后通过以下方式进行设置
初始化完整示例
import 'package:qt_apm_sdk/qt_apm_sdk.dart';
void main() {
final QuickTrackingFlutterApmSdk qtApmSdk = QuickTrackingFlutterApmSdk(
name: '',
bver: '',
flutterVersion: '3.10.0',
engineVersion: 'd44b5a94c9',
enableLog: true,
enableTrackingPageFps: true,
enableTrackingPagePerf: true,
errorFilter: {
"mode": "ignore",
// "rules": [RegExp('RangeError')],
"rules": [],
},
trackDomain: "配置收数域名",
initFlutterBinding: MyApmWidgetsFlutterBinding.ensureInitialized,
// onError: (exception, stack) {},
);
qtApmSdk.init(appRunner: (observer) async {
// 确保去掉原有的WidgetsFlutterBinding.ensureInitialized() ,以免出现重复初始化绑定的异常造成无法正常初始化,
// SDK内部已通过initFlutterBinding入参带入继承的WidgetsFlutterBinding实现初始化操作
// 依赖ensureInitialized()初始化的代码可在此调用
// 需要异步获取设置应用名称和版本号可在此回调中操作
// SDK实例化的设置可先将name和bver 为 "",然后通过以下方式进行设置
// 如:qtApmSdk.name = 'app_demo';
qtApmSdk.name = 'app_demo';
qtApmSdk.bver = '1.0.0+9';
return MyApp(observer);
});
}
class MyApmWidgetsFlutterBinding extends ApmWidgetsFlutterBinding {
@override
void handleAppLifecycleStateChanged(AppLifecycleState state) {
// 添加自己的实现逻辑
// print('AppLifecycleState changed to $state');
super.handleAppLifecycleStateChanged(state);
}
static WidgetsBinding ensureInitialized() {
// 等到初始化完成了再去Binding
if (WidgetsBinding.instance == null) {
MyApmWidgetsFlutterBinding();
}
return WidgetsBinding.instance;
}
}
2.3 注册监听
在MyApp(StatelessWidget
或者StatefulWidget
)中注册NavigatorObserver,实现MyApp(this._navigatorObserver)的构造方法,在navigatorObservers中添加ApmNavigatorObserver.singleInstance
class MyApp extends StatelessWidget {
MyApp([this._navigatorObserver]);
NavigatorObserver? _navigatorObserver;
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
routes: routes,
initialRoute: "/",
navigatorObservers: <NavigatorObserver>[
_navigatorObserver ?? ApmNavigatorObserver.singleInstance
],
);
}
}
3. SDK API
3.1 页面监控
页面性能监测
页面性能检测功能默认关闭,如需开始需要设置enableTrackingPagePerf为true
示例:
final QuickTrackingFlutterApmSdk qtApmSdk = QuickTrackingFlutterApmSdk(
...
enableTrackingPagePerf: true,
...
);
qtApmSdk.init(appRunner: (observer) async {
qtApmSdk.name = 'qt_demo';
qtApmSdk.bver = '应用版本+构建号';
return MyApp(observer);
});
页面帧率分析
页面帧率(FPS)表示每秒传输的图像帧数,用于衡量视频流畅度和画面动态处理能力。需要使用SDK的ApmScrollController实例,注册滚动控制器用于监听滚动事件。
import 'package:flutter/material.dart';
import 'package:qt_apm_sdk/qt_apm_sdk.dart';
class ScrollLazyLoadPage extends StatefulWidget {
@override
_ScrollLazyLoadPageState createState() => _ScrollLazyLoadPageState();
}
class _ScrollLazyLoadPageState extends State<ScrollLazyLoadPage> {
List<String> imageUrls = [];
int page = 1;
// 使用APM滚动控制器(ApmScrollController)
ScrollController _scrollController = ApmScrollController();
bool isLoading = false;
@override
void initState() {
super.initState();
fetchData();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
fetchData();
}
});
}
Future<void> fetchData() async {
if (!isLoading) {
setState(() {
isLoading = true;
});
// Simulating a delay of 2 seconds
await Future.delayed(Duration(seconds: 2));
final List<String> urls = [
'https://img_01.jpg',
'https://img_02.jpg',
'https://img_03.jpg',
...
];
try {
setState(() {
imageUrls.addAll(urls);
isLoading = false;
});
} catch (e) {}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Scroll Lazy Load Demo'),
),
body: GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemCount: imageUrls.length + 1,
itemBuilder: (context, index) {
if (index == imageUrls.length) {
return Center(
child:
isLoading ? CircularProgressIndicator() : SizedBox.shrink(),
);
}
return Card(
child: Image.network(
imageUrls[index],
fit: BoxFit.cover,
),
);
},
),
);
}
}
3.2 异常监控
Dart异常
SDK自动监控Dart异常信息,包含app内的同步、异步异常(runZonedGuarded所管理的所有异常)、framework异常、用户自定义上报的异常,上报的数据可以在平台中查看。
请注意:Dart异常支持设置单设备每天上报Dart异常条数的上限,默认20个,最高支持120条/天
自定义异常
captureException(类型:Function)
入参配置 | 含义 | 是否必传 | 类型 |
exception | 异常摘要 | 是 | Exception |
stack | 异常堆栈 | 否 | String |
extra | 自定义属性 | 否 | Map<String, dynamic> |
案例一
import 'package:qt_apm_sdk/qt_apm_sdk.dart';
void main() {
Isolate isolate = await Isolate.spawn(runIsolate, []);
// 监听isolate异常
isolate.addErrorListener(RawReceivePort((pair) {
var error = pair[0];
var stacktrace = pair[1];
// 主动采集isolate异常
ExceptionTrace.captureException(
exception: Exception(error),
stack: stacktrace.toString());
}).sendPort);
}
案例二
import 'package:qt_apm_sdk/qt_apm_sdk.dart';
void main() {
try {
List<String> numList = ['1', '2'];
print(numList[5]);
} catch (e) {
// 主动捕获上报代码执行异常
ExceptionTrace.captureException(
exception: Exception(e), extra: {"user": '123'});
}
}
3.3 黑白名单设置ErrorFilter
用于设置采集的项的黑白名单,可以在黑名单和白名单中选择其一,如果选择白名单的方式,那么只有符合标准的页面会被采集,如果选择的是黑名单的方式,那么符合标准的页面不会被采集。
此项非必须参数,用于判断是否过滤日志,包含如下属性:
属性 | 含义 | 默认 | 类型 |
mode | 匹配模式
| ignore | 枚举值 ignore|match |
rules | 匹配规则集合
| [],该默认值表示黑名单为空,日志全部上报 | Array<string | RegExp > |
示例:
void main() {
QuickTrackingFlutterApmSdk(
name: '应用或者模块名称',
// 过滤异常筛选
errorFilter: {
"mode": "match",
"rules": [RegExp('RangeError')],
},
....
);
}
4. Native SDK 集成
iOS SDK请参考文档:iOS SDK
Android SDK请参考文档:Android SDK
5.远程配置
目前我们根据不同的应用权限提供了设备PV采样率和单设备日志最大条数上报的设置功能,采样率设置生效时间:修改采样率配置后,服务端需要15分钟下发最新的配置,SDK侧在服务端配置生效后,再次冷启动时会拉取最新的配置,并将拉取到的配置缓存在本地,下次设备重新冷启动(SDK初始化)时配置生效。
【PV采样率】解释:设备启动后产生的页面访问行为会采集异常、性能、帧率的日志,通过云配采样率控制以设备为维度的采集行为。例: PV采样率 5% 100台,设备通过端上的随机计算是否能命中那5%的概率,命中即可通过PV行为采集各类型日志。
远程配置默认规则:
flutter监控:默认开启
PV采样率:默认5%,最高可调整到100%;pv采样率也会影响flutter监控,如果pv采样率过低,当采样率未命中时,flutter 监控功能也不生效
页面性能上限:支持设置单设备每天上报页面性能的上限,默认200个,最高支持1000条/天
Dart异常上限:支持设置单设备每天上报Dart异常条数的上限,默认20个,最高支持120条/天
6. 验证SDK运行
调整采样率
在验证前需要将Flutter PV采样率调至100%以确保可以命中日志采样,线上可以按需配置
查看日志面板
如遇数据查询不到的情况,请检查产品【开关与采样配置】中的 【Flutter监控】是否是开启的状态(默认开启)