你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 移動端監控體系之技術原理剖析

移動端監控體系之技術原理剖析

編輯:IOS開發基礎

原文

在這樣一個注重用戶體驗的時代,APM 技術快速發展,國內更是百花齊放,最近對各個公司的 APM 產品有一個調研,並在此基礎上進行了自己的實踐。這裡就從 iOS 的角度出發,談談自己對移動端 APM 的技術上的理解,並提供相對應的實例。

何為 APM

APM 的全稱是Application performance management,即應用性能管理,通過對應用的可靠性、穩定性等方面的監控,進而達到可以快速修復問題、提高用戶體驗的目的。

國內各大公司都有自己的一套監控體系,這個系統可能是自己研發,也可能是第三方提供,當然對於這個數據為王的時代,很多有實力的公司傾向於自主研發,掌握核心數據。比較有代表性的 APM 產品有:聽雲、阿裡百川、騰訊 bugly、NewRelic、OneAPM、網易雲捕等

說到監控,那麼指標是我們所關注的呢?如下所示

  • 網絡請求:成功率、狀態碼、流量、網絡響應時間、HTTP與HTTPS的 DNS 解析、TCP握手、SSL握手(HTTP除外)、首包時間等時間

  • 界面卡頓、卡頓堆棧

  • 崩潰率、崩潰堆棧

  • Abort 率:也就是由於內存過高的等原因,被系統殺死的情況

  • 交互監控:頁面加載時間、頁面的交互痕跡

  • 維度信息:地域、運營商、網絡接入方式、操作系統、應用版本等

  • 其他:內存、幀率、CPU使用率、啟動時間、電量等

聊聊原理

卡頓檢測

當應用發生卡頓的時候,一般會伴隨著掉幀,所以幀率是最容易想到的指標來判斷卡頓。對於線下的測試環境,我們可以使用幀率來對開發做一些提示,告訴他們可能發生了卡頓。但是幀率不穩定性較高,所以一般會采取另一種方式來做卡頓檢測。那就是Runloop,對於細節可以查看 Runloop 源碼,會發現對於事件的處理主要就是在kCFRunLoopBeforeSources和kCFRunLoopBeforeWaiting狀態之間,還有kCFRunLoopAfterWaiting之後。那我們就可以對兩個狀態進行監控,如果消耗時間太久,就代表著卡頓的發生。

QQ截圖20170302093230.png

阿裡百川

上圖摘自阿裡百川,如圖所示,我們會對卡頓次數做一個判斷,如果次數為1,但時間超時,則為單次耗時較長的卡頓,如果次數到達閥值,則證明是連續短時間卡頓。

當卡頓發生之後,我們為了定位,會收集當時的一個堆棧情況,在此你可以使用 PLCrashReporter 來做,也可以自己研發一個堆棧收集庫(可參考這裡來做)

對於實例,網上已經有很多開源的項目,你可以參考這個

崩潰檢測

對於崩潰的情況,一般是由 Mach異常或 Objective-C 異常(NSException)引起的。我們可以針對這兩種情況抓取對應的 Crash 事件。

Mach 異常捕獲

如果想要做mach 異常捕獲,需要注冊一個異常端口,這個異常端口會對當前任務的所有線程有效,如果想要針對單個線程,可以通過 thread_set_exception_ports注冊自己的異常端口,發生異常時,首先會將異常拋給線程的異常端口,然後嘗試拋給任務的異常端口,當我們捕獲異常時,就可以做一些自己的工作,比如,當前堆棧收集等。

對於如何注冊一個異常端口,這裡有示意圖和 PLCrashReporter 可以參考

852671-4569d4e79d4754a4.jpg

Unix 信號捕獲

對於Mach 異常,操作系統會將其轉換為對應的 Unix信號,所以如果你對Mach不熟悉的話,也可以通過注冊signalHandler的方式來做信號異常。對於實例,你可以參考這裡

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細節寫入Crash日志,上傳到後台做數據分析

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

Abort 率檢測

目前對於內存過高被殺死的情況是沒有辦法直接統計的,一般通過排除法來做百分比的統計,原理如下

  • 程序啟動,設置標志位

  • 程序正常退出,清楚標志

  • 程序Crash,清楚標志

  • 程序電量過低導致關機,這個也沒辦法直接監控,可以加入電量檢測來輔助判斷

  • 第二次啟動,標志位如果存在,則代表Abort一次,上傳後台做統計

852671-04d1ec27b6247a8b.jpg

阿裡百川

交互監控

對於頁面的加載時間,這個比較容易實現,直接通過Runtime hook對應的生命周期方法即可,比如 viewDidLoad、viewWillAppear等

對於用戶的交互痕跡,比如點擊了那個按鈕、跳轉到了那個頁面,這些信息偏於用戶行為的收集,我們也獨立研發了一個無埋點的SDK,專門來做用戶行為數據的收集與分析,核心也是基於 hook AOP的思想。細節可以參考我同事的作品

網絡監控

對於成功率、狀態碼、流量,以及網絡的響應時間之類的,我們可以主要可以通過兩種方式來做

  • 針對URLConnection、CFNetwork、NSURLSession三種網絡做Hook,hook的具體技術可以是method swizzle 也可以是Proxy、Fishhook之類的

  • 也可以使用 NSURLProtocol 對網絡請求的攔截,進而得到流量、響應時間等信息,但是NSURLProtocol有自己的局限,比如NSURLProtocol只能攔截NSURLSession,NSURLConnection以及UIWebView,但是對於CFNetwork則無能為力

對於第一種方式可以Hook哪些方法的,可以參考這個圖

852671-43a0fb796e1a93c1.jpg

對於 HTTP與HTTPS 的 DNS 解析、TCP握手、SSL握手(HTTP除外)、首包時間等時間的統計,稍有難度

QQ截圖20170302092922.png

但是,因為我們所使用的URLConnection、CFNetwork、NSURLSession底層都是 BSDSocket,所以可以嘗試在socket上動手腳來實現效果,類似於通過ViewController的生命周期方法來統計頁面加載時間的做法,我們Hook socket相關的方法來做,比如通過hook socket連接時的 connect方法,拿到tcp握手的起始時間,通過hook SSLHandshake方法,在SSLHandshake執行的時候拿到 SSL握手的起始時間等。目前聽雲已經提供了 HTTP 的分段時間查詢功能,大家去體驗下

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

OSStatus SSLHandshake(SSLContextRef ctx)

但是對於 iOS 9 Apple 加入 ATS 新特性,並要求開發者使用 HTTPS,我在 iOS9、10上對 HTTPS 網絡請求Hook socket方法時候,有一些方法hook 失效,猜想應該是Apple 進行了加固、加密,導致一些系統方法沒辦法hook,所以在 iOS9、10 上無法通過socket來取得HTTPS網絡的分段時間

不過apple在 iOS 10 推出一個API,可以在 iOS10 版本以上進行網絡信息的收集

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

打印結果如下

(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

當然,對於網絡各層次的時間獲取,如果你有好的方案,希望您可以留言告知。同時對於一些維度信息和內存等基礎指標,很容易獲取,這裡就不細談了

大禮包

在調研和學習APM技術的過程中,發現了很多優秀的博客,所以在此推薦給大家,有需要的可以自取

  • 蘑菇街移動端全鏈路跟蹤保障體系

  • 美團外賣移動端性能監測體系實現

  • 微信讀書 iOS 質量保證及性能監控

  • 網易NeteaseAPM iOS SDK技術實現分享

  • 阿裡百川碼力APP監控來了 重量級選手進入APM市場

  • APM最佳實踐系列文章專題合輯

  • 手機淘寶:億級用戶APP的快速運維交付實踐

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved