接入iOS
SDK 引入
iOS SDK 最低兼容系统版本 iOS 8.0。
SDK集成
手动集成
下载 SDK。
拖拽 QAPM.framework 文件到 Xcode 工程内(请勾选 Copy items if needed 选项)。
在 TARGETS > Build Phases-Link Binary Libraries 添加依赖库。
- libc++.dylib (libc++.tbd)
- libz.dylib (libz.tbd)
在工程的 Other Linker Flags 中添加-ObjC参数。
将framework里面的js_sdk.js文件导入到工程根目录。
- 如果需要使用证书校验,需要把上报移动监控环境的证书放在QAPM.framework > QAPM.bundle文件下(如果没有请新建),然后工程右键添加add Files(copy items if needed)将bundle证书添加到项目中。
- 证书类型只支持xxx.cer类型的DER编码二进制,单一证书,如果是在google浏览器的web栏下载证书请注意格式选择,Safari下载目前没有格式限制。
cocoaPods 集成
暂时只支持本地的 cocoaPods 集成。
将带有 QAPM 字样的整个文件夹,拖入到工程根目录带有 Pods 字样的文件夹下面。
在工程根目录 Podfile(不是 Podfile.lock)文件中,加入如下内容(注意路径的正确性)。
pod 'QAPM', :path => './Pods/QAPM'
以上步骤完成之后,cd 到 Podfile 目录,然后执行pod install 指令即可。
注意:如果需要使用证书校验,需要把上报移动监控环境的证书放在QAPM.framework > QAPM.bundle文件下(如果没有请新建),然后执行pod install命令。
初始化 SDK 及 Web 端环境配置
进入 QAPM 页面的配置 > 产品配置,可以查看到 AppKey,该 key 在初始化接入中需要使用。
在工程的 AppDelegate.m 文件导入头文件
#import <QAPM/QAPM.h>
如果是 Swift 工程,请在对应 bridging-header.h 中导入。
初始化 QAPM 在工程AppDelegate.m 的application:didFinishLaunchingWithOptions:方法中初始化:
void loggerFunc(QAPMLoggerLevel level, const char* log) {
\#ifdef RELEASE
if (level <= QAPMLogLevel_Event) { ///外发版本log
NSLog(@"%@", [NSString stringWithUTF8String:log]);
}
\#endif
\#ifdef GRAY
if (level <= QAPMLogLevel_Info) { ///灰度和外发版本log
NSLog(@"%@", [NSString stringWithUTF8String:log]);
}
\#endif
\#ifdef DEBUG
if (level <= QAPMLogLevel_Debug) { ///内部版本、灰度和外发版本log
NSLog(@"%@", [NSString stringWithUTF8String:log]);
}
\#endif
}
\- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/// 设置QAPM 日志输出
NSLog(@"qapm sdk version : %@", [QAPM sdkVersion]);
[QAPM registerLogCallback:loggerFunc];
// 设置QAPM 开启的监控功能
\#ifdef DEBUG
[[QAPMModelStableConfig getInstance] setupModelAll:1];
\#else
[[QAPMModelStableConfig getInstance] setupModelStale:1];
\#endif
//私有云用户根据实际情况配置。
[QAPMConfig getInstance].host =@"自定义host";
// appconfigHost内外网用户为默认值,私有云用户需要自定义设置。
[QAPMConfig getInstance].appconfigHost = @"私有云设置";
[QAPMConfig getInstance].customerAppVersion = @"设置app自定义版本号";
//根据实际情况设置userid 和deviceID
//设备唯一标识deviceID,例如IDFV配合Keychain使用
[QAPMConfig getInstance].userId = @"设置userId";
[QAPMConfig getInstance].deviceID = @"自定义deviceId";
/// 启动QAPM
[QAPM startWithAppKey:@"产品唯一的appKey"];
return YES;
}
参数设置
受当前监管部门要求,在用户同意隐私合规之前请勿调用QAPM的任何接口,同时SDK类产品禁止获取UDID等个人信息,但是QAPM需要设备级的唯一标识符用于确定设备的唯一性并计算相关的用户性能指标,因此QAPM开放设备标识符的相关接口供开发者自行设置相关字段,请开发者根据自身业务情况设置设备唯一标识符与Userid信息。若配置的相关字段不符合预期则有可能影响相关指标的准确性。
// 当用户授权后,方可正常初始化QAPM
if (isAgree) { }
//启动耗时函数的第一个打点
// 需要传入设备的唯一标识,如IDFV配合Keychain使用
[QAPMConfig getInstance].deviceID = @"自定义deviceId";
//用户user ID、第三方登录账号,此接口可以多次在代码位置使用
[QAPMConfig getInstance].userId = @"设置userId";
工作日志配置
在调用[QAPM startWithAppKey:]启动 QAPM SDK 前,设置日志输出函数, 可以根据不同发布版本情况进行输出日志控制:
void loggerFunc(QAPMLoggerLevel level, const char* log) {
\#ifdef RELEASE
if (level <= QAPMLogLevel_Event) { ///外发版本log
NSLog(@"%@", [NSString stringWithUTF8String:log]);
}
\#endif
\#ifdef GRAY
if (level <= QAPMLogLevel_Info) { ///灰度和外发版本log
NSLog(@"%@", [NSString stringWithUTF8String:log]);
}
\#endif
\#ifdef DEBUG
if (level <= QAPMLogLevel_Debug) { ///内部版本、灰度和外发版本log
NSLog(@"%@", [NSString stringWithUTF8String:log]);
}
\#endif
}
\- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/// 设置QAPM 日志输出
[QAPM registerLogCallback:loggerFunc];
/// ...
/// 设置启动QAPM SDK
}
在接入完成 SDK 后,通常情况下会通过分析日志来确定监控功能是否已经开启。
监控功能未开启时,日志如下:
监控功能开启时,日志如下:
通过初始化日志,可以看到初始化成功,各个监控功能开启。
功能配置
崩溃监控
功能开启
QAPMMonitorTypeCrash Crash 日志会在下次启动 SDK 后上报数据。
在 FOOM 与deadlock卡死退出后,将在下次启动上报上一次记录的相关堆栈信息。FOOM在非APPstore环境下是全量上报,App Store模式下数据会有2%抽样。
功能开启校验
普通崩溃(normal crash)的上报
在触发 normal crash 的上报时,请不要将数据线连接 Xcode,触发完 normal crash 后,下次重启 App 的时候即可看到上报信息,该上报日志可通过 Mac 自带的控制台查看上报日志,日志如下:
流畅度采集
功能开启
卡顿时间在主线程超过200ms阈值则采集堆栈进行上报。
在工程对应的类里面导入头文件 #import <QAPM/ QAPMBlueProfile.h>;
- 滑动场景的卡顿监控
在相关页面进行如下代码的打点:
\- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[QAPMBlueProfile stopTrackingWithStage:NSStringFromClass([self class])];
}
\#pragma mark - TableView Delegate
\- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[QAPMBlueProfile beginTrackingWithStage:NSStringFromClass([self class])];
}
\- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if(!decelerate){
[QAPMBlueProfile stopTrackingWithStage:NSStringFromClass([self class])];
}
}
\- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[QAPMBlueProfile stopTrackingWithStage:NSStringFromClass([self class])];
}
功能配置
@interface QAPMBlueProfile: NSObject
/**
开始记录掉帧,建议滑动开始时调用
\* @param stage 用来标识当前页面(一般为当前VC类名)
*/
\+ (void) beginTrackingWithStage:(NSString *)stage;
/**
掉帧,滑动结束时调用
\* @param stage 用来标识当前页面(一般为当前VC类名)
*/
\+ (void)stopTrackingWithStage:(NSString *)stage;
@end
功能开启校验
- 卡顿个例的上报、超过阈值后立马上报
- 流畅度的上报、在对应的页面快速滑动、关掉App后,下次启动会看到对应的数据
启动体验监控
功能开启
功能说明
- 使用启动耗时监控功能,可以统计出 App 进程创建时间到 App 第一帧UI上屏的时间。
- 当启动时间超过阈值(默认4000ms),则会上报个例详情。个例详情包括启动耗时、自动打点区间、自定义打点区间和启动过程堆栈。
相关接口
**@interface** QAPMLaunchProfile : NSObject
/**
设置自定义打点区间开始,该区间需要在启动时间区间内。begin与end的scene需要一致。
@param scene 场景名
*/
\- (void)setBeginTimestampForScene:(NSString *)scene;
/**
设置自定义打点区间结束,该区间需要在启动时间区间内。begin与end的scene需要一致。
@param scene 场景名
*/
\- (void)setEndTimestampForScene:(NSString *)scene;
@end
代码示例
在 main 函数进行启动启动监控组件:
int main(int argc, char * argv[]) { @autoreleasepool { [QAPMLaunchProfile didEnterMain]; return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
功能开启校验
- 启动指标的上报、其中plugin:14是对应的启动指标的数据、每次都会上报
- 启动个例的上报、其中plugin:66是对应的启动个例的数据、启动个例数据会额外抓取对应的启动阶段的堆栈、冷启动阶段的个例上报阈值是超过4s会上报
- 热启动指标和个例的上报、热启动监控的统计逻辑是App在前台退回后台超过3min后返回前台的时候会报启动指标、返回前台的过程中如果主线程卡顿时长超过2s会上报相应的个例数据。
网络监控
功能开启
默认初始化的时候已经开启、无需额外打点。
功能开启校验
- HTTP 监控上报
Webview体验监控
功能开启
注意:如果使用手动集成的方式,需要将 framework 里面的 js_sdk 以 Add Files to 方式引入到工程中;如果是用的 cocoaPods 集成方式则不需要。
如果用到 TMFWebOffline 离线包功能,工程里面的 wkwebview 相关页面的头文件需要引入#import
\#import <TMFQWebView/QBWKWebView.h>
@interface WKWebviewViewController ()<WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler,TMFWebOfflineWebViewControllerProtocol>
{
TMFWkWebView *wkWebView;
}
目前 WKWebView 支持 iOS >= 11 。
该功能能够监控 Web 网络资源加载耗时、jserror 监控。Web监控默认1‰的抽样,接入时可以在产品设置—白名单中添加设置的userid
Web 端配置
iOS SDK 配置
类文件中添加 #import
导入 SDK 头文件。 在 WKWebView 的代理方法 webView:didFinishNavigation:中添加如下代码,以提供 Web 获取 native 相关信息接口。
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
[webView evaluateJavaScript:[QAPMWebViewProfile qapmBaseInfo:@" "] completionHandler:nil];
[webView evaluateJavaScript:[QAPMWebViewProfile qapmJsStart] completionHandler:nil];
}
Webview 上报日志信息可通过 Safari 浏览器调试 Webview 的方式查看。
功能开启校验
Webview 和 JSerror 的上报
Webview 和 jserror 的上报,在查看 Webview 的上报日志时,需要借助浏览器中的开发者工具,通过浏览器查看上报日志。
注意:SDK5.2.1版本之后,webview的上报改为原生端上报,对应的plugin:41和plugin:43,部分上报日志如下
Https双向证书校验
集成SDK的时候可以自行选择,其中在bundle文件添加证书即为证书校验、没有添加则不进行校验,根据初始化日志即可判断当前设置是否有加入证书校验。
符号表配置
利用已上报的数据个例上传符号表。根据个例页面的构建ID找到对应的符号表,可以使用官方atos命令翻译个例页面某行堆栈,确认符号表和翻译正常。
上传符号表及手动翻译说明
在有数据上报的前提下,来到前端页面,下面以Crash为例子上传符号表
1)进入到移动监控前端页面,找到崩溃-崩溃分析,往下滑找到问题列表
2)前置准备
请将后缀为 .dSYM 的符号表文件直接压缩成 zip 文件进行上传,如有多个需要打包在一起统一上传从系统上获取的dSYM文件的默认名称为XXX.app.dSYM,需要确保不要修改默认名称
需要确保zip文件里面直接就是一个或多个 XXX.app.dSYM,不能额外增加文件夹层级,可以有多个 .dSYM文件
需要确保XXX.app.dSYM文件夹里面的层级是默认层级: Contents/Resources/DWARF/XXX
3)点击进入,往下滑,在右侧的模块里找到上传(更新)dSYM文件的按钮
4)上传.dSYM文件
在对应的问题详情页中可以通过点击上传.dSYM文件或者更新.dSYM文件弹出对应的上传框
点击选择文件并选择文件后即自动上传任务,同一时间仅可执行一个上传任务。
成功上传后您可以通过该弹窗下载和更新符号表。
5)手动翻译
当成功上传文件后即可点击堆栈信息上方的翻译按钮对堆栈进行翻译。以翻译的堆栈可以重新翻译,重新翻译将会以最新上传的文件为基础重新执行翻译功能。
若未上传对应的.dSYM文件,则无法点击翻译按钮。
使用到的开源信息说明
This [QAPM] project is built on and with the aid of the following open source projects. Credits are given to these projects.
The below open source projects in this distribution may have been modified by THL A29 Limited, all such modifications are under Copyright (C) 2022 THL A29 Limited.
- KSCrash
Copyright (c) 2012 Karl Stenerud
Licencing: MIT (https://opensource.org/licenses/MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in the documentation of any redistributions of the template files themselves (but not in projects built using the templates).
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- OOMDetector
Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
If you have downloaded a copy of the OOMDetector binary from Tencent, please note that the OOMDetector binary is licensed under the MIT License.
If you have downloaded a copy of the OOMDetector source code from Tencent, please note that OOMDetector source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of OOMDetector into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within OOMDetector.
A copy of the MIT License is included in this file.
Other dependencies and licenses:
Open Source Software Licensed Under the BSD 3-Clause License:
----------------------------------------------------------------------------------------
- fishhook
Copyright (c) 2013, Facebook, Inc. All rights reserved.
Terms of the BSD 3-Clause License:
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of [copyright holder] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Terms of the MIT License:
---------------------------------------------------
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.