移動端監(jiān)控體系之技術(shù)原理剖析

在這樣一個(gè)注重用戶體驗(yàn)的時(shí)代碘耳,APM 技術(shù)快速發(fā)展,國內(nèi)更是百花齊放孕豹,最近對各個(gè)公司的 APM 產(chǎn)品有一個(gè)調(diào)研涩盾,并在此基礎(chǔ)上進(jìn)行了自己的實(shí)踐。這里就從 iOS 的角度出發(fā)励背,談?wù)勛约簩σ苿佣?APM 的技術(shù)上的理解春霍,并提供相對應(yīng)的實(shí)例。

何為 APM

APM 的全稱是Application performance management椅野,即應(yīng)用性能管理终畅,通過對應(yīng)用的可靠性、穩(wěn)定性等方面的監(jiān)控竟闪,進(jìn)而達(dá)到可以快速修復(fù)問題、提高用戶體驗(yàn)的目的杖狼。

國內(nèi)各大公司都有自己的一套監(jiān)控體系炼蛤,這個(gè)系統(tǒng)可能是自己研發(fā),也可能是第三方提供蝶涩,當(dāng)然對于這個(gè)數(shù)據(jù)為王的時(shí)代理朋,很多有實(shí)力的公司傾向于自主研發(fā)絮识,掌握核心數(shù)據(jù)。比較有代表性的 APM 產(chǎn)品有:聽云嗽上、阿里百川次舌、騰訊 bugly、NewRelic兽愤、OneAPM彼念、網(wǎng)易云捕等

說到監(jiān)控,那么指標(biāo)是我們所關(guān)注的呢浅萧?如下所示

  • 網(wǎng)絡(luò)請求:成功率逐沙、狀態(tài)碼、流量洼畅、網(wǎng)絡(luò)響應(yīng)時(shí)間吩案、HTTP與HTTPS的 DNS 解析、TCP握手帝簇、SSL握手(HTTP除外)徘郭、首包時(shí)間等時(shí)間
  • 界面卡頓、卡頓堆棧
  • 崩潰率丧肴、崩潰堆棧
  • Abort 率:也就是由于內(nèi)存過高的等原因残揉,被系統(tǒng)殺死的情況
  • 交互監(jiān)控:頁面加載時(shí)間、頁面的交互痕跡
  • 維度信息:地域闪湾、運(yùn)營商冲甘、網(wǎng)絡(luò)接入方式、操作系統(tǒng)途样、應(yīng)用版本等
  • 其他:內(nèi)存江醇、幀率、CPU使用率何暇、啟動時(shí)間陶夜、電量等

聊聊原理

卡頓檢測

當(dāng)應(yīng)用發(fā)生卡頓的時(shí)候,一般會伴隨著掉幀裆站,所以幀率是最容易想到的指標(biāo)來判斷卡頓条辟。對于線下的測試環(huán)境,我們可以使用幀率來對開發(fā)做一些提示宏胯,告訴他們可能發(fā)生了卡頓羽嫡。但是幀率不穩(wěn)定性較高,所以一般會采取另一種方式來做卡頓檢測肩袍。那就是Runloop杭棵,對于細(xì)節(jié)可以查看 Runloop 源碼,會發(fā)現(xiàn)對于事件的處理主要就是在kCFRunLoopBeforeSourceskCFRunLoopBeforeWaiting狀態(tài)之間,還有kCFRunLoopAfterWaiting之后氛赐。那我們就可以對兩個(gè)狀態(tài)進(jìn)行監(jiān)控魂爪,如果消耗時(shí)間太久先舷,就代表著卡頓的發(fā)生。

阿里百川

上圖摘自阿里百川滓侍,如圖所示蒋川,我們會對卡頓次數(shù)做一個(gè)判斷,如果次數(shù)為1撩笆,但時(shí)間超時(shí)捺球,則為單次耗時(shí)較長的卡頓,如果次數(shù)到達(dá)閥值浇衬,則證明是連續(xù)短時(shí)間卡頓懒构。

當(dāng)卡頓發(fā)生之后,我們?yōu)榱硕ㄎ辉爬蓿瑫占?dāng)時(shí)的一個(gè)堆棧情況胆剧,在此你可以使用 PLCrashReporter 來做,也可以自己研發(fā)一個(gè)堆棧收集庫(可參考這里來做

對于實(shí)例醉冤,網(wǎng)上已經(jīng)有很多開源的項(xiàng)目秩霍,你可以參考這個(gè)

崩潰檢測

對于崩潰的情況,一般是由 Mach異骋涎簦或 Objective-C 異常(NSException)引起的铃绒。我們可以針對這兩種情況抓取對應(yīng)的 Crash 事件。

Mach 異常捕獲

如果想要做mach 異常捕獲螺捐,需要注冊一個(gè)異常端口颠悬,這個(gè)異常端口會對當(dāng)前任務(wù)的所有線程有效,如果想要針對單個(gè)線程定血,可以通過 thread_set_exception_ports注冊自己的異常端口赔癌,發(fā)生異常時(shí),首先會將異常拋給線程的異常端口澜沟,然后嘗試拋給任務(wù)的異常端口灾票,當(dāng)我們捕獲異常時(shí),就可以做一些自己的工作茫虽,比如刊苍,當(dāng)前堆棧收集等。

對于如何注冊一個(gè)異常端口濒析,這里有示意圖和 PLCrashReporter 可以參考

Unix 信號捕獲

對于Mach 異常正什,操作系統(tǒng)會將其轉(zhuǎn)換為對應(yīng)的 Unix信號,所以如果你對Mach不熟悉的話号杏,也可以通過注冊signalHandler的方式來做信號異常埠忘。對于實(shí)例,你可以參考這里

signal(SIGHUP, signalHandler);
signal(SIGINT, signalHandler);
signal(SIGQUIT, signalHandler);
   
signal(SIGABRT, signalHandler);
signal(SIGILL, signalHandler);
signal(SIGSEGV, signalHandler);
signal(SIGFPE, signalHandler);
signal(SIGBUS, signalHandler);
signal(SIGPIPE, signalHandler);

NSException 捕獲

對于NSException異常馒索,也比較容易處理莹妒,通過注冊NSUncaughtExceptionHandler捕獲異常信息即可,將拿到的NSException細(xì)節(jié)寫入Crash日志绰上,上傳到后臺做數(shù)據(jù)分析

 // register the uncaught exception handler
 NSSetUncaughtExceptionHandler(&handler);

Abort 率檢測

目前對于內(nèi)存過高被殺死的情況是沒有辦法直接統(tǒng)計(jì)的旨怠,一般通過排除法來做百分比的統(tǒng)計(jì),原理如下

  • 程序啟動蜈块,設(shè)置標(biāo)志位
  • 程序正常退出鉴腻,清楚標(biāo)志
  • 程序Crash,清楚標(biāo)志
  • 程序電量過低導(dǎo)致關(guān)機(jī)百揭,這個(gè)也沒辦法直接監(jiān)控爽哎,可以加入電量檢測來輔助判斷
  • 第二次啟動,標(biāo)志位如果存在器一,則代表Abort一次课锌,上傳后臺做統(tǒng)計(jì)
阿里百川

交互監(jiān)控

對于頁面的加載時(shí)間,這個(gè)比較容易實(shí)現(xiàn)祈秕,直接通過Runtime hook對應(yīng)的生命周期方法即可渺贤,比如 viewDidLoadviewWillAppear

對于用戶的交互痕跡请毛,比如點(diǎn)擊了那個(gè)按鈕志鞍、跳轉(zhuǎn)到了那個(gè)頁面,這些信息偏于用戶行為的收集方仿,我們也獨(dú)立研發(fā)了一個(gè)無埋點(diǎn)的SDK固棚,專門來做用戶行為數(shù)據(jù)的收集與分析,核心也是基于 hook AOP的思想仙蚜。細(xì)節(jié)可以參考我同事的作品

網(wǎng)絡(luò)監(jiān)控

對于成功率此洲、狀態(tài)碼、流量鳍征,以及網(wǎng)絡(luò)的響應(yīng)時(shí)間之類的黍翎,我們可以主要可以通過兩種方式來做

  • 針對URLConnectionCFNetwork艳丛、NSURLSession三種網(wǎng)絡(luò)做Hook匣掸,hook的具體技術(shù)可以是method swizzle 也可以是ProxyFishhook之類的
  • 也可以使用 NSURLProtocol 對網(wǎng)絡(luò)請求的攔截氮双,進(jìn)而得到流量碰酝、響應(yīng)時(shí)間等信息,但是NSURLProtocol有自己的局限戴差,比如NSURLProtocol只能攔截NSURLSession送爸,NSURLConnection以及UIWebView,但是對于CFNetwork則無能為力

對于第一種方式可以Hook哪些方法的,可以參考這個(gè)圖

對于 HTTP與HTTPS 的 DNS 解析袭厂、TCP握手墨吓、SSL握手(HTTP除外)、首包時(shí)間等時(shí)間的統(tǒng)計(jì)纹磺,稍有難度

但是帖烘,因?yàn)槲覀兯褂玫?code>URLConnection、CFNetwork橄杨、NSURLSession底層都是 BSDSocket秘症,所以可以嘗試在socket上動手腳來實(shí)現(xiàn)效果,類似于通過ViewController的生命周期方法來統(tǒng)計(jì)頁面加載時(shí)間的做法式矫,我們Hook socket相關(guān)的方法來做乡摹,比如通過hook socket連接時(shí)的 connect方法,拿到tcp握手的起始時(shí)間采转,通過hook SSLHandshake方法聪廉,在SSLHandshake執(zhí)行的時(shí)候拿到 SSL握手的起始時(shí)間等。目前聽云已經(jīng)提供了 HTTP 的分段時(shí)間查詢功能氏义,大家去體驗(yàn)下

int connect(int, const struct sockaddr *, socklen_t) __DARWIN_ALIAS_C(connect);

OSStatus SSLHandshake(SSLContextRef ctx) 

但是對于 iOS 9 Apple 加入 ATS 新特性锄列,并要求開發(fā)者使用 HTTPS,我在 iOS9惯悠、10上對 HTTPS 網(wǎng)絡(luò)請求Hook socket方法時(shí)候邻邮,有一些方法hook 失效,猜想應(yīng)該是Apple 進(jìn)行了加固克婶、加密筒严,導(dǎo)致一些系統(tǒng)方法沒辦法hook,所以在 iOS9情萤、10 上無法通過socket來取得HTTPS網(wǎng)絡(luò)的分段時(shí)間(糾正:fishhook 無法 hook socket 的原因:https://github.com/facebook/fishhook/issues/40

不過apple在 iOS 10 推出一個(gè)API鸭蛙,可以在 iOS10 版本以上進(jìn)行網(wǎng)絡(luò)信息的收集

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics 

打印結(jié)果如下

(Fetch Start) 2017-02-24 09:03:06 +0000
(Domain Lookup Start) 2017-02-24 09:03:06 +0000
(Domain Lookup End) 2017-02-24 09:03:06 +0000
(Connect Start) 2017-02-24 09:03:14 +0000
(Secure Connection Start) 2017-02-24 09:03:14 +0000
(Secure Connection End) 2017-02-24 09:03:16 +0000
(Connect End) 2017-02-24 09:03:16 +0000
(Request Start) 2017-02-24 09:03:16 +0000
(Request End) 2017-02-24 09:03:16 +0000
(Response Start) 2017-02-24 09:03:16 +0000
(Response End) 2017-02-24 09:03:16 +0000

當(dāng)然,對于網(wǎng)絡(luò)各層次的時(shí)間獲取筋岛,如果你有好的方案娶视,希望您可以留言告知。同時(shí)對于一些維度信息和內(nèi)存等基礎(chǔ)指標(biāo)睁宰,很容易獲取肪获,這里就不細(xì)談了

大禮包

在調(diào)研和學(xué)習(xí)APM技術(shù)的過程中,發(fā)現(xiàn)了很多優(yōu)秀的博客柒傻,所以在此推薦給大家孝赫,有需要的可以自取

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市红符,隨后出現(xiàn)的幾起案子青柄,更是在濱河造成了極大的恐慌伐债,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件致开,死亡現(xiàn)場離奇詭異峰锁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)喇喉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門祖今,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拣技,你說我怎么就攤上這事∷D浚” “怎么了膏斤?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邪驮。 經(jīng)常有香客問我莫辨,道長,這世上最難降的妖魔是什么毅访? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任沮榜,我火速辦了婚禮,結(jié)果婚禮上喻粹,老公的妹妹穿的比我還像新娘蟆融。我一直安慰自己,他們只是感情好守呜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布型酥。 她就那樣靜靜地躺著,像睡著了一般查乒。 火紅的嫁衣襯著肌膚如雪弥喉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天玛迄,我揣著相機(jī)與錄音由境,去河邊找鬼。 笑死蓖议,一個(gè)胖子當(dāng)著我的面吹牛虏杰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拒担,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼嘹屯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了从撼?” 一聲冷哼從身側(cè)響起州弟,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钧栖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后婆翔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拯杠,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年啃奴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了潭陪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡最蕾,死狀恐怖依溯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘟则,我是刑警寧澤黎炉,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站醋拧,受9級特大地震影響吭敢,放射性物質(zhì)發(fā)生泄漏吃衅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望腊瑟。 院中可真熱鬧厌均,春花似錦汗贫、人聲如沸司蔬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忿峻。三九已至,卻和暖如春辕羽,著一層夾襖步出監(jiān)牢的瞬間逛尚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工刁愿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绰寞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓铣口,卻偏偏與公主長得像滤钱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子脑题,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容