一. Rollbar可以幫你解決哪些問題
無特別說明,文中Rollbar統指Rollbar-flutter
1. 代碼復用

Rollbar官方檔案說是純Dart實作,該特征意味著自帶”代碼復用”光環,
如圖當接入端(Third-APP)呼叫Rollbar SDK時表示包含的網路(例外資料上傳等)和存盤(例外存盤管理)可達到復用效果,

若Flutter例外監控框架非純Dart實作(第三篇中Bugsnag),就存在代碼無法復用問題,如圖,Dart-Crash-SDK是這層殼依賴對端SDK,最終導致各平臺(android,ios,…)都須對端SDK(android-crash-sdk, ios-crash-sdk,…)適配,導致網路和存盤邏輯對端SDK都須各自實作一遍,嚴重邏輯重復,

由此在做軟體多端架構設計時,Dart側可理解成是多平臺公共代碼集合,如果存在多端邏輯功能代碼完全可以抽離到Dart側以復用,減少測驗和人力成本,
2. 定制包裝操作
前面兩篇文章我們知道,捕獲到原始例外后對其中的Error和StackTrace有相當部分的作業是對原始例外資料的包裝再將包裝類資料發送給對端或者后臺,不同框架包裝程序是不一樣的,如下圖中Catcher框架包裝后類物件是Report,Bugsnag對例外進行兩次包裝,第一次是BugsnagError,第二次是BugsnagEvent,

這很好理解,因為對于同一事物不同框架的需求是不一樣的,不同需求注定了不同的包裝行為,
原始例外資料就像一條魚,口味清淡的Catcher選擇清蒸,重口味的Bugsnag選擇紅燒,不同框架就是不同口味的吃魚人,而Rollbar 將包裝行為抽象化,將原始的魚以某種方式提供給你,讓你享受自由烹飪樂趣,
3. 執行緒切換
例外產生后有很多耗時操作,如原始例外資料包裝中存在讀取額外欄位,例外的存盤,查詢,加密,上報等,耗時操作都在main isolate 中做, 勢必會影響到main isolate的UI 構建等行為,例外資料量比大時UI會有卡頓情況,就像圖中情況,

Rollbar支持將例外耗時處理操作交給子isolate(crash isolate),讓main isolate保持專注做UI構建等以提高應用的流暢度,

4. 追溯生成路徑
該需求與第三篇Flutter例外監控 - 叁 |從bugsnag原始碼學習如何追溯例外產生路徑 相同
該需求目的是能完整記錄用戶操作的整個行為路徑,這樣達到清晰指導用戶操作程序,對問題的定位很有幫助,可以理解成一個小型的埋點系統,只是該埋點系統只是針對例外來做的,
區別在代碼層面實作,bugsnag中有自動添加和手動添加路徑兩種情況,Rollbar中只有手動添加,但是手動添加分類更加細化,比如圖中將Breadcrumb構造程序被分成Breadcrumb.error、Breadcrumb.navigation、Breadcrumb.widget、Breadcrumb.log 對應不同圖示事件,

話說,追溯例外生成路徑需求是標配么? 目前看Bugsnag和Rollbar都有實作,
二. 如何使用
- 將包添加到您的檔案中:
pubspec.yaml
dependencies:
rollbar_flutter: ^0.3.0-beta
- 運行
flutter pub get
代碼中配置:
import 'package:rollbar_flutter/rollbar.dart';
Future<void> main() async {
const config = Config(
//accessToken到https://rollbar.com/注冊獲取
accessToken: 'YOUR-ROLLBAR-ACCESSTOKEN',
package: 'rollbar_flutter_example');
await RollbarFlutter.run(config, () {
runApp(const MyApp());
});
}
- 要求
- Dart SDK >= 2.7.0
- Flutter >= 1.20.0
- A Rollbar account
三. 原理決議
Rollbar是Flutter例外框架,當然少不了讀這類原始碼套路,直接拿出第三篇文章中的通用閱讀路徑, 按照如下流程一步步走:
1. Flutter例外監控點
- 接入端通過RollerFlutter.run 進入到Rollbar內部邏輯,
重點關注Config中默認的四個變數:
- Notifier:控制發送事件是通過主執行緒還是其他執行緒中發送,
- Transformer:對例外資料進行轉換的轉換器,
- Wrangler: 提供對例外資料二次包裝機會回傳最終發送的真實資料,
- Sender: 將Wrangler提供的真實資料發送,


- 通過FlutterError.onError(21行)和runZonedGuarded(13行)兩個監控點邏輯處理,將例外收攏到Rollbar.error方法中

- 將原始例外以Event方式交給Notifier.notify(15行),

- 通過步驟1中Config提供默認實作知道步驟3中_notifier是IsolatedNotifier,這樣下圖中(14行)事件最侄訓發送到子執行緒中(45行),
這里主要涉及到isolate雙向通信知識,不清楚可以看下這個帖子Flutte 指北 -> Isolate
- 40~43 : 實際拿到的是步驟1中傳入的幾個默認值,其中telemetry變數可以理解成資料庫封裝物件用來快取例外資料的,
- 46~49 : 在轉換Event之前,需要對資料庫中快取的例外進行處理,其中資料庫中快取資料有兩類1. breadcrumb 2. Event ,49會對正常Event進行過期判斷,如果過期就洗掉掉,
- 51~53: 這個通過默認wrangler獲取真實資料,
- 54:sender發送真實資料到服務器等,

至此流程圖如下:
2. 生成例外包裝類
- 10行:Event轉換成Data物件,主要是添加一些除了Error和StackTrack之外資訊,比如客戶端資訊(當前OS系統,OS版本,dart版本,平臺CPU內核數目等)、包名,事件等級,環境等,
- 11行:Data物件交給Transformer轉換器,讓開發者可以自定義自己的轉換行為,
- 12行:回傳最終真實資料Payload,

例外資料包裝流程:

3. 操作包裝類
上面步驟中經過對Event二次封裝,生成最終包裝類為Payload, 最后該類轉換成字串發送到Rollbar后臺,

四.如何進行執行緒切換
上面分析可知執行緒切換通過Notifier實作,執行緒切換思路:通過Config配置自定義Notifier值來指定例外處理運行執行緒,AsyncNotifier是main UI isolate, IsolateNotifier會新建子執行緒執行例外相關操作,
Notifier定義
abstract class Notifier {
// notifier version to be updated with each new release: [todo] automate
static const version = '0.4.0-beta';
static const name = 'rollbar-dart';
Sender get sender;
Wrangler get wrangler;
Telemetry get telemetry;
FutureOr<void> notify(Event event);
FutureOr<void> dispose();
}
Notifier及子類關系圖

子isolate處理好處
默認初始化IsolatedNotifier.spwan 將產生一個新執行緒,
總結了幾點好處:
- 發送事件之前Telemetry會做資料庫相關增加,查詢和洗掉操作,這個耗時,
- Wrangler物件會通過Transformer對Event進行二次保證操作,這個程序也可能耗時,
- Sender.send發送事件的時候,如果當前應用某個時間段例外頻繁,在主執行緒也可能影響UI,
綜上將可能耗時都放到異步執行緒,可以提高主執行緒流暢性,
五. 如何定制包裝類
上面分析可知,包裝程序通過Transformer來實作,自定義包裝類思路:通過Config配置自定義Transformer值來實作自定義處理例外資料邏輯,可以進行加密等,
Transformer定義
abstract class Transformer {
FutureOr<Data> transform(Data data, {required Event event});
}
Transformer子類
Config默認實作是這個,如果想自定義資料包裝程序,可以復寫其中transform,對其中date和event操作,
class NoopTransformer implements Transformer {
const NoopTransformer(Config _);
@override
Data transform(Data data, {required Event event}) => data;
}
六. 設計模式相關
1. 單一職責原則
類功能抽象精準,清晰的職能分工:
- Isolate切換模塊,
Notifier子類實作, - 轉換模塊:
Transformer物件給了自定義和默認的轉換方式, - 傳輸模塊:
Wrangler將提供最終真實資料并傳輸給sender, - 發送模塊:
Sender子類實作,可以擴展出httpSender等, - 存盤模塊:
Telemetry對資料庫的包裝,可插入,查詢 例外和例外路徑物件,
2. 可插拔設計
可插拔意味更自由的功能和更開閉的設計,Rollbar像堆積木一樣,將包裝,傳輸,發送,存盤通過組合方式統一配置起來更具靈活性,

通過非空命名建構式提供默認實作,模塊直接是以組合配置,外部可設定和替換,滿足開閉原則,
const Config({
this.notifier = IsolatedNotifier.spawn,
this.wrangler = DataWrangler.new,
this.transformer = NoopTransformer.new,
this.sender = PersistentHttpSender.new,
});
PS: 一直沒想明白Dart中建構式的多非空可選引數與構建者模式有啥不同,感覺前者完全可以替換構建者模式的場景,哪位大佬能告訴我應用場景區別?
七. 其他
考慮到篇幅原因,文章分析了主要流程,其實還有很多點值得學習和借鑒,如
- 例外存盤和序列化相關邏輯,
- 多stacktrace處理,例如:Android平臺中的PlatformException,
- Dart2.15中建構式拆分,
八. 問題及說明
- 官方flutter還是beta版本官網創建專案的時候沒有flutter專案圖示選擇,可以不選,直接將客戶端accesstoken拿到example中即可,
- 在發送程序中會報accesstoken的錯誤,這個是因為之前accesstoken配置錯誤的情況下記錄沒發送出去導致的,將應用卸載或者應用資料庫刪掉后,再用最新的accesstoken測驗即可,
九. 優點和缺點
優點
- 支持發送執行緒切換,
- 支持dart層資料庫保持資料,
- 支持多stacktrace處理,例如:Android平臺中的PlatformException,
- 整個流程看起來比較順暢,組件間分工明確,且支持config可配置,
- 支持追溯例外路徑,
缺點
- 例外追溯路徑沒有針對導航和網路進行自動埋點的設計都是手動埋點有些費事,這完全可以借鑒Bugsnag來做,
- 雖然Rollbar官方說是純Dart實作,但是它存盤相關底層用了sqlite3,這玩意是通過通道來實作的,非純Dart實作存在依賴對端原生功能的風險,是否可以考慮用純Dart的hive來替換,
十. 參考鏈接
Flutter例外監控 - 叁 | 從bugsnag原始碼學習如何追溯例外產生路徑 - 掘金
Releases · rollbar/rollbar-flutter
Flutter
如果覺得文章對你有幫助,點贊、收藏、關注、評論,一鍵四連支持,你的支持就是我創作最大的動力,
?? 本文原創聽蟬 公眾號:碼里特別有禪 歡迎關注原創技術文章第一時間推送 ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/541711.html
標籤:其他
上一篇:視頻實時自然美顏, 無懼素顏上鏡
下一篇:視頻實時自然美顏, 無懼素顏上鏡
