SDK 無埋點技術在百分點的探索和實踐

分類:設計 時間:2016-10-14

本文為『移動前線』群在9月21日的分享總結整理而成,轉載請注明來自『移動開發前線』公眾號。

嘉賓介紹:

唐星,百分點架構師。畢業于中南民族大學,開源技術愛好者,曾活躍于多個移動社區并擔任社區版主、并跟論壇合作編寫過Android/ios的技術書籍,從2010年開始從事移動端軟件開發,專注于移動端開發,現任職于百分點,負責整個移動端的產品和業務,積極推進百分點移動端推薦和分析SDK多個版本的技術創新和開發迭代。

大家好,我分享的主題是《百分點SDK無埋點技術實踐》,將介紹百分點由原來的手動寫代碼的埋點技術如何發展出不需要寫代碼的無埋點技術。

今天帶來SDK無埋點技術,大家可以了解到SDK無埋點技術是怎么實現的,百分點通過之前的埋點技術怎么演化了這種無埋點技術。我分三個部分來講一下。

第一部分,就是講一下什么是SDK無埋點技術;

第二部分,SDK無埋點技術如何實現?講一些技術細節;

第三部分,在實踐中遇到的一些坑和解決方法。

我們看第一部分,這一塊介紹一下我們無埋點技術,既然我們要做這個無埋點,肯定要解決一些問題。這個解決什么問題呢?主要三個問題。第一,開發者依賴性,如果做埋點,需要開發者下載第三方SDK,熟悉SDK編寫埋點代碼。我們目的就是不用開發人員來做這些。通過運維人員也是可以達到這個效果。第二個問題就是解決成本過高,我們可以通過這種可視化操作,把代碼和配制進行分離,這樣效率更高,降低成本。第三,避免代碼寫死。這樣就是可以動態更新,更加高效。

首先介紹一下埋點,大家知道一個大數據分析系統經過4個階段,第一個階段數據采集,把數據采集上來。第二,傳輸到服務器,第三,進行建模和統計。我們都是做數據清洗,把臟數據清洗掉。第四步進行數據展示。這一塊兒,百分點會把這些數據做推薦,還有一些標簽和畫像。而埋點就發生在這個源頭第一階段。所謂埋點就是通過在代碼的關鍵部位植入統計代碼。

這個是埋點代碼。很簡單,就是有一個評論按紐,在點擊的時候,我們拿一些評論的信息,用戶ID,還有評論,最后就是SDK通過這一段代碼,把這些信息發送到服務端。這個就是埋點代碼。

我們看一下無埋點,說了這么多,并不是一行代碼不用植入。還是需要寫一些代碼,需要調用SDK初始化代碼,我們的目標是什么?少寫代碼,盡可能通過幾行代碼,就可以把SDK集成進去,關鍵業務統計指標都是通過程序來自動收集,通過后臺的配制。然后,可以做什么呢?就是熱更新。通過這種熱更新的方法,直接改后臺配制,不需要再一次發布版本。第三,就是可視化操作。可以不依賴開發者,一些實施人員都是通過后臺的配制,就達到埋點的配制,還有新增埋點改動都是很方便的實現。最后就是配制和代碼,可以很靈活地擴展,動態地更新。

說了這么多,大家肯定想看一下無埋點什么樣子?我精心挑選了兩張高清無碼照給大家看一下。

簡單說一下無埋點的流程。這是無埋點管理端,因為SDK是沒有界面可以跟用戶交互的。我們采用手機搖一搖來跟服務器建立連接,我們看下一個界面。我們把當前這個APP界面,可以直接投到這個服務端,服務端會把當前可點擊這些元素都列出來,并且框起來。然后,這里我當時是對“活動”按鈕做了一個埋點的操作。埋點操作完以后,這邊有一個生效,生效了以后,其他用戶使用的時候,點擊活動的時候就會采集這個數據,直接發到服務端。

我們接著看一下,可以做埋點和無埋點的比較。埋點和無埋點,就是相輔相成的,埋點是適用于一些比較復雜的應用場景。比如說我除了想知道這個點擊事件,還想多帶一些參數。例如加入購物車行為,我還想知道商品價格和數量等信息,這個還是需要通過埋點寫代碼,把詳細的參數加入到代碼里面采集這些信息。而無埋點針對一些簡單的操作,一個按紐統計點了沒有?或者點擊多少次?

無埋點整體架構

接下來第二部分,介紹一下實現SDK無埋點整個思路。看一下整體的架構。

整體的架構,后臺的管理端,SDK都是屬于客戶端,有兩臺服務器,一個配制服務器和一個通信服務器,SDK和配制界面跟這個服務器進行交互,也是把這些生成配制寫到配制服務器,SDK真正采集數據的時候,就是把這個數據發送到這個探頭服務。最終進入這些大數據的存儲Hive里面。

APP的界面如何傳輸到配制界面?我們當時做這一塊兒設計的時候,想到兩個方案,第一個,通過一些遠程桌面的協議來實現。大家之前做過這種應該有了解,我之前也是做過這些東西。第一,比較的復雜,用在這種場景里面不太現實。再就是通過這種遠程桌面協議把PC桌面弄到手機上面。反過來,這樣做的很少。所以,最終我們是舍棄了這種方案,采用第二種。第二種就是比較的簡單了,我對當前的屏幕進行截圖,截圖完了以后做一些處理。做一些壓縮,然后傳到服務端,服務端進行展現,就把屏幕截圖展現出來。

控件信息獲取及ID生成技術

屏幕截圖做完了,下一步,需要在管理界面進行配置,對于可點擊的組件進行配置,就需要把這些界面框起來。你需要把它展現出來。我們接著看一下,怎么拿到屏幕控件信息。這個是算整個技術里面比較關鍵的一點。這一塊兒主要就是三個問題。第一,就是獲取時機。第二,就是拿控件什么信息,什么信息是需要用到的。第三,就是比較關鍵的,如何生成控件的唯一ID,ID是在程序內部生成。需要保證在不同的手機上面,這些ID是一樣的。還要保證每一次啟動ID都是不變。

首先是Android:

這種通用ID規則我們現在基本上解決了90%的問題,還是有一些情況會導致這個ID有一些問題,后面會講到的。

然后,接下來我們可以看一下iOS,同樣的,也是面臨三個問題。

iOS主要是用Runtime技術,通過hook把點擊事件系統函數指針替換一下,換成自己的函數。然后,我們先做一些處理,處理完以后,我們再調系統原來函數。這樣的話就可以自動捕獲,發送到服務端,從而采集到這個數據。

遇到的問題和解決辦法

第三部分,講一下我們在實現無埋點技術的時候,遇到了什么坑?以及采用什么方法來解決這些坑。

長連接斷開的問題,我們之前是設計每隔5秒發送一次截圖,一般不會產生斷開。但是,后面做了一些優化,我們不會每隔5秒就發,這樣就會導致這個鏈路長時間沒有數據。然后,我們解決方法也是采取了業界通用的方法,發一個心跳,通過發一個心跳來保證這個鏈路一直是活著的。

第二個問題就是搖一搖遇到的問題,我們遇到的問題是這樣的,你拿著手機搖一搖,什么時候連接成功呢?你得給用戶一個反饋,要不用戶就是一直搖下去,我們后來想的方法是,搖成功給他一個振動,振動了,用戶有反饋,就知道這個連接成功了,不需要搖了。然后,就是帶來另外一個問題。有時候運動當中,又會產生一些誤操作,就是導致手機會振一下。這個怎么解決呢?我們就想了一下,可以通過給服務端有一個交互,管理界面里面發現有一個請求過來要連了會有一個確認的按鈕,用戶確認之后,SDK收到確認消息以后,我們再去振動。這樣的話,既可以給用戶反饋,也不會說在它誤操作情況下振動。這樣就不會造成誤操作,也不會無緣無故地進行振動。

界面傳輸的優化,因為在整個配制過程當中,傳輸數據量最大的就是屏幕的截圖。怎么把這個優化一下?就可以更好地提升我們的體驗度,還有流暢性。圖片采用jpeg格式,把圖片質量選擇0.6,剛好是可以看清楚的。然后,也最大限度地降低了這個圖片大小。

然后,整個傳輸效率,有這樣一個問題。我在當前界面,默認就是5秒傳一次。我點了一下,我在當前一個列表界面,點了一下切換到詳情界面。最壞的情況下就是等5秒,加上網絡傳輸效果,管理界面就看到新的屏幕。這種體驗是很差的,因為實時性太差。所以,這一塊做了一個優化。盡量讓它實時傳過去,我們在屏幕切換的時候,主動發一次截圖。這樣的話,等的時間就是網絡傳輸的時間,不用等5秒固定的時間。這一塊用戶體驗上面就是更流暢一些。

有的時候屏幕界面沒有任何的變化的,這個時候每隔5秒傳一次沒有必要的。所以,我們把屏幕截圖做一個md5進行保留,傳輸時對比md5,當切換到下一個的時候,我們就發新的屏幕截圖。這樣就會減少很多不必要的屏幕的傳輸。然后,也會節省很多的流量。

控件ID重復的問題。前面說過我們的ID生成規則可以解決90%的問題,但是,有一些問題還是解決不了。生成ID重復,重復的話就會產生一個什么樣的效果和問題?同樣兩個按紐,一個注冊,對于注冊定義了一個埋點,就是注冊點擊,用戶實際操作的時候點登陸的時候也是發過來一個注冊點擊消息。這樣就是統計不準,因為這種比較的特殊,我們采用的解決方案,通過服務端發一些特殊配制。把這些配制里面,因為這兩個button里的text不一樣,一個是注冊,一個是登陸。我們把text信息放在ID的這個生成規則里面,最終生成兩個不同的ID,也是可以解決這個問題。

SDK技術發展趨勢

最后,我想給大家分享一下SDK的技術發展的一些趨勢,我覺得主要是三個。

第一,自動化。怎么可以做到用戶要集成一個SDK的時候,可以盡量簡單地自動化集成,比如說,幾行代碼可以把SDK集成,如果可以做到更智能一些就更好。用戶把SDK發給你,你通過工具來做一些操作。把你SDK植入進去,用戶基本上無感應。

第二就是可視化,簡單重復操作封裝成可視化的,把開發者解放出來,讓運維他們做這些操作。開發者可以專心于SDK核心模塊優化和功能的拓展。

第三就是動態更新。移動開發一些限制,很難達到動態更新,目前我們主要采用一些技術例如熱修復技術,還有一些是用腳本實現邏輯。這個是一個趨勢,將來做SDK都是朝著這個目標。

QA環節

Q:Android里你們怎么監控Fragment頁面的埋點的,使用了什么技術?

A:Fragment頁面現在無法支持這種自動埋點的監控,現在只支持到activity.

Q:Android端如何確定設備的唯一ID?能百分百確定唯一ID么?

A:Android端可以使用mac地址imei等信息來確定設備的唯一ID,不能百分百,因為Android下有山寨機,一般是把設備的幾種ID都發往服務端,服務端有個生成唯一ID的規則,這樣能保證大部分的情況。

Q:為什么無埋點不能拿到商品價格等更具體的一些數據信息呢?

A:理論上也可以拿到,但是比較復雜,需要服務端跟客戶端約定好一些特殊場景,例如告訴sdk,商品價格的控件類名,是什么類型,然后sdk根據這些配置信息再去動態獲取。這種可變性太大,不具有通用性。

Q:請問一下截圖的時候,iOS是在hook到的方法里進行截圖么,截圖完畢后就發送到服務器?

A:對,是在hook的函數里做截圖,以及遍歷當前可點擊控件的信息一起發送給服務器。

Q:iOS怎么確定唯一設備碼?

A:iOS 8以后主流做法都是生成一個GUID,然后存儲到KeyChain里,這樣只要不刷機或者恢復出廠設置就能存活很長一段時間,7的時候可以用序列號,6的時候用mac地址,再往前用UDID.

Q:現在已經開始流行無埋點技術了?你們這個技術對性能有沒有什么影響?還有你們上報一次截圖流量耗費多少?

A:無埋點算是一種嘗試吧可以解決一些應用場景,對性能基本沒影響,因為最終是生成的一些配置,sdk把這些配置轉化為邏輯代碼;上報一次截圖流量不是很大,而且上報截圖的操作都是建議在WiFi下進行的,而且這個配置只是開發人員做一次,其他安裝app的用戶不需要。

Q:既然是無埋點,我們的Android SDK怎么做到去獲取到各個控件view的呢?

A:會攔截所有activity的onresume函數,然后在這里面去遍歷當前的view tree,找到感興趣的控件。

Q:iOS可以通過讀plist文件達到同樣的效果,而且帶參數的也同樣支持,不用手動寫代碼打點,實現起來也簡單很多,為何不用這種方式呢?

A:plist你就寫死到客戶端,這樣就無法保證服務端動態修改了。

Q:感覺是類似appium的方式,獲取頁面元素位置信息,但是這個實時截圖就算壓縮了也要比純文本的埋點信息大很多,如果是高頻次操作,這里如何能保證埋點發送的準確性?對服務器要求呢?

A:截圖這些都是發生在配置過程,配置完了只是生成配置文件下發到所有客戶端,所以這塊對服務器沒什么壓力。就跟你sdk啟動時請求服務器一段配置一樣。

Q:看到你介紹的無埋點是簡單的點擊等事件,有埋點是一些和上下文環境相關的復雜些的事件收集。你們項目中,無埋點和有埋點的比例大約是多少的呢?

A:這個主要看app的類型和需求了,目前我們對于一些展現性質的簡單app,無埋點可以超過埋點,但是對于一些業務復雜的電商類app,埋點的還是占多數。

Q:能監控到PopWindow 和 Dialog 或者動態生成的view控件嗎?

A:第一版不可以,后續版本支持了PopWindow和Dialog,動態生成的view得看生成的時機,如果在我們攔截的時機之后估計就拿不到了。

Q: 按理說一個界面上傳一次截圖和當前可點擊控件的信息就可以了,為什么要每5秒發送一次,當前頁面又不會變化。還有就是多久拉一次配置信息?

A:這里是為了描述我們開發過程中的優化,最早的時候就是5秒發,后續做了很多優化,這塊就是做md5值比對,發現界面不變就不發了。

Q:如果HOOK安全可靠,是否可以通過window去HOOK取subview的frame進行繪制,將數據記錄下來之后按照一定格式壓縮保存上傳至服務器在進行還原是不是更快捷更節省流量?另外一般情況下數據團隊只對關心的按鈕、用戶停留時間比較關心,采用frame+自帶信息(手動攜帶的user-id等)+控件ID 進行聚合在后臺分析展開是否可行?

A:這種理論上也可以,但是這種需要考慮的情況比較多,當前可能有多個window,然后當前window的viewcontroller的堆棧結構,每個viewcontroller里的view可能有多層;而且你需要把所有信息傳給服務器,然后服務器根據這些信息來繪制,對服務端的邏輯處理要求也高。

所以最終我們選擇的是截圖,然后用戶來標記感興趣的控件。

活動推薦

QCon上海免費專場報名: 高并發與實時處理架構設計 將分享大規模實時流處理平臺架構以及實時消息推送架構,并從穩定性和實時性兩個方面探討即時通訊云實踐,還將揭示海量數據推送服務背后的挑戰,希望能幫助開發者了解解決現實問題的新思路。 戳閱讀原文免費報名!


↓↓ 點擊 閱讀原文 進入活動報名頁面。


Tags: 服務器 移動設計

文章來源:http://mp.weixin.qq.com/s?__biz=MzA3ODg4MDk0Ng==


ads
ads

相關文章
ads

相關文章

ad