| RFC-0171:改善診斷路徑 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 推出 CML 和 CMC 公用程式,改善診斷路徑 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2022-05-19 |
| 審查日期 (年-月-日) | 2022-06-23 |
摘要
提案:在 cmc 和 CML 中提供公用程式,簡化樹狀結構中各處的診斷通訊協定 (fuchsia.logger.LogSink 和 fuchsia.diagnostics.InspectSink) 路由,並減少缺少記錄或檢查資料的 DX 痛點。雖然本文著重於檢查和記錄,但也可以用來改善大多數元件可能希望提供的其他通訊協定 (例如 fuchsia.tracing.provider.Registry) 的可用性。
提振精神
使用記錄的 DX 痛點是元件需要在各處路由 fuchsia.logger.LogSink:
在生產元件、測試、RealmBuilder路徑等。記錄是大多數 Fuchsia 體驗的核心部分,我們預期幾乎每個元件和測試都會使用記錄。
RFC-0168 建議使用 fuchsia.inspect.InspectSink 通訊協定,讓元件發布檢查結果,進而改善效能並減少技術債。就像 fuchsia.logger.LogSink 我們預期所有 (或至少大部分) 元件都會使用 Inspect 檢測工具。現在每個元件都可以 expose /diagnostics to framework,讓每個元件都能公開檢查,並提供給 Archivist。朝向通訊協定發展時,我們必須確保所有元件都能繼續公開檢查資料,這對開發人員來說非常重要,有助於在執行階段偵錯元件的行為。
這不符合人體工學,且容易出錯,因為我們需要更新所有 CML,才能手動將這個通訊協定路由至目前正在編寫 Inspect 的所有元件。LogSink 也有同樣的問題,尤其是在測試中,很容易忘記將 LogSink 路由至受測元件,導致記錄遺失,浪費開發人員的時間。
元件管理服務會利用元件的 LogSink,列印歸因於該元件的路由錯誤。這項功能可讓開發人員快速發現路由錯誤,進而提升 DX。不過,如果 LogSink 未正確路由,這些錯誤最終會歸因於元件管理服務的全域系統記錄,開發人員查看自己的元件記錄時,更容易忽略這些錯誤。
本文嘗試在 cmc 和 CML 中導入公用程式,簡化這兩種通訊協定到每個元件的路由,以改善這種情況。
元件架構計畫審查路徑 API,並構思如何讓模型更一致且更易於使用。這項作業需要數季的時間,因此建議採用漸進式做法,使用現有的基本元素並加以擴充。
利害關係人
講師:leannogasawara@google.com
審查者:
- crjohns@google.com
- geb@google.com
- hjfreyer@google.com
- shayba@google.com
- zarvox@google.com
已諮詢:
- bryanhenry@google.com
- cgonyeo@google.com
- jmatt@google.com
- thatguy@google.com
社交化:這項設計以 Google 文件形式呈現,並列出替代方案,供利害關係人深入討論,最後形成決策文件。
設計
為方便開發人員在目前的元件功能路徑系統下,絕不遺漏記錄和檢查,並遵循最低權限和階層式隔離原則,以及繼續公開檢查,我們將開發下列項目:
cmc必須提供優惠檢查工具。- 可為 CML 中的所有子項和集合提供能力。
- 用於診斷的新 CML 分片。
RealmBuilder會自動為所有元件提供診斷功能。
cmc 必須提供的優惠和用途
cmc 會取得指令列選項 --must-offer-protocol,其中包含要驗證下列陳述式是否成立的通訊協定名稱清單:
對於資訊清單中宣告的每個子項和集合,每個必要通訊協定清單中定義的通訊協定,都會存在來自某個來源的
OfferDecl。
此外,cmc 會取得對等的指令列選項 --must-use-protocol,用於檢查對等項目,但適用於 UseDecl。
GN 和 Bazel 工具會更新,以便在呼叫 cmc 時,將 fuchsia.logger.LogSink 和 fuchsia.diagnostics.InspectSink 傳遞至這些選項。
如要完全停用這項檢查,無論如何為資訊清單呼叫 cmc,開發人員都可以在 CML 檔案中新增下列內容 (這是 CML 中導入的新語法):
{
disable: {
must_use_protocol: [ "fuchsia.logger.LogSink", "fuchsia.diagnostics.InspectSink" ],
must_offer_protocol: [ "fuchsia.logger.LogSink", "fuchsia.diagnostics.InspectSink" ],
}
}
如要避免將 LogSink 或 InspectSink 傳送給部分子項,開發人員可以:
- 使用能力路徑:將通訊協定
from: "void"傳送至要關閉單一方案的子項/集合。 - 從所需來源手動轉送通訊協定。
這些功能源自 bootstrap 和 root 領域,因此需要特別處理:
bootstrap:會開啟這個選項,確保LogSink路由至啟動程序中的所有元件。此外,系統還會將void中的Inspect/LogSink優惠新增至封存者。root:會開啟這個選項,確保系統將LogSink從 Archivist 轉送至所有同層級項目。由於bootstrap是公開這項能力的項目,我們會將void中的優惠新增至bootstrap的Inspect/LogSink。
我們希望藉此減少 Fuchsia 開發人員錯過記錄或檢查資料的機率。
zarvox@ 為這個部分建構了原型 (和關係鏈)。
允許向 CML 中的所有孩子和集合提供能力
為改善所有子項的路由傳送 DX,我們將在 CML 中導入語法糖,允許將路由傳送能力「傳送至所有子項和集合」。
這個語法糖可依下列方式使用:
offer: [
{
protocol: "fuchsia.logger.LogSink",
from: "parent",
to: "all",
}
]
編譯含有該語法的 CML 檔案時,系統會產生 N 個 OfferDecl,其中 N 是元件擁有的集合和子項總數。
系統會在 cmc 中設下閘道,確保 OfferDecl 僅以目標 all 使用,且僅限於前一節所述新選用引數中定義的通訊協定。
CML 分片
系統會建立下列分片:
// syslog/use.shard.cml
{
use: [
{ protocol: "fuchsia.logger.LogSink" },
],
}
// syslog/offer.shard.cml
offer: [
{
protocol: "fuchsia.logger.LogSink",
from: "parent",
to: "all"
}
]
// inspect/use.shard.cml
{
use: [
{ protocol: "fuchsia.diagnostics.InspectSink" },
],
}
// inspect/offer.shard.cml
offer: [
{
protocol: "fuchsia.diagnostics.InspectSink",
from: "parent",
to: "all"
}
]
系統會更新下列現有分片:
syslog/client.shard.cml:包含syslog/use.shard.cml和syslog/offer.shard.cml。inspect/client.shard.cml:包含inspect/use.shard.cml和inspect/offer.shard.cml。
只執行路由作業而不執行任何程式的邏輯元件,可以使用 offer.shard.cml。需要使用這些通訊協定,但需要設定要將哪些內容傳送給子項的元件,可以使用 use.shard.cml。其餘使用者則可使用標準且方便的 client.shard.cml。
如果元件沒有子項或集合,但仍使用 client.shard.cml (因為使用通訊協定),則由於這是語法糖,只會展開為 OfferDecl,因此分片中的 offer to all 陳述式會是無運算。
為方便起見,我們會提供包含這兩個 client.shard.cml 檔案的 diagnostics/client.shard.cml。
RealmBuilder 更新,支援 offer to all
為方便將診斷通訊協定路徑傳送至所有受測元件,RealmBuilder 會收到幾項更新,允許將通訊協定路徑傳送至所有子項和集合:
自動為所有子項和集合提供 LogSink 和 InspectSink。在 Rust 中,這可能如下所示:
builder .add_route( Route::new() .capability(Capability::protocol_by_name("fuchsia.diagnostics.InspectSink")) .from(Ref::parent()) .to(Ref::all()), ) .await?;由於我們預期所有測試都會這麼做 (某些特殊情況除外),RealmBuilder 會自動將這些通訊協定路徑傳送至所有元件。這似乎與
cmc和 CML 採用的方法不一致,但RealmBuilderAPI 已在某些領域有所不同,可提供更便利的工作流程,更適合用於測試。由於我們預期 99% 的時間會將這些通訊協定路徑傳送至測試元件,因此我們會教導RealmBuilder自動執行這項操作,並提供關閉這項功能的途徑:let builder = RealmBuilder::new().await?; … let instance = builder .route_logs_to_all(false) // defaults to true .route_inspect_to_all(false) .build() .await;
實作
- 更新
cmc,以便支援 CML 中的新標記和offer to all。 - 新增包含
offer LogSink to all的syslog/offer.shard.cml。 - 更新樹狀結構中的
cmc用法,使用新旗標,並更新可能缺少路徑的現有 CML。GN 和 Bazel SDK 會更新,但直到 OOT CML 遷移完畢,提供完整的一組產品前,預設會使用一組必要的通訊協定[]。 - 更新樹狀結構外的
cmc用法,以使用新旗標,並更新可能缺少路徑的現有 CML (利用供應項目分片)。 - 更新 GN 和 Bazel SDK,要求使用診斷通訊協定。
- 包含
syslog/client.shard.cml中的syslog/offer.shard.cml。 - 推出後,請重構使用供應項目分片但不再需要的 OOT 資訊清單,因為這些資訊清單已透過用戶端分片納入。
效能
cmc 會執行一些額外工作,但預期不會對編譯時間造成重大影響。
安全性考量
這項變更符合元件架構安全屬性,尤其是最低權限原則和階層式隔離原則。
隱私權注意事項
不會影響隱私權。
測試
新的 cmc 功能會經過單元測試。
說明文件
cmc 會更新為包含新選項,而 CML 會更新為說明新的 offer to all 功能。
缺點、替代方案和未知事項
在 Environment 中使用 debug_capabilities
這是主要考慮的替代方案。在這個替代方案中,我們會擴充 fuchsia.sys2.Environment,使其具有 diagnostics_capabilities,就像 debug_capabilities 一樣,或是將 debug_capabilities 變成 diagnostics_capabilities,或僅將 debug_capabilities 用於診斷通訊協定,讓樹狀結構中的任何元件 from: diagnostics 或 from: debug 都能使用。
這項功能會在元件管理服務安全性政策中受到限制,確保只有根 Archivist 和測試中嵌入的 Archivist 才能使用。
優點:
- 樹狀結構中的任何元件都可以使用
InspectSink和LogSink。 - 與世界現況一致,每個元件都可以公開檢查。
- 開發人員不必花時間找出元件未記錄的原因,也不必在測試中尋找缺少的供應項目,因此 DX 獲得提升。
- 可靜態檢查能力點對點使用情形。
- 除非明確使用能力,否則所有元件的命名空間都會以「nothing」開頭。
- 涵蓋透過
fuchsia.component.Realm/CreateChild建立的動態元件。
缺點:
- 不再提供明確的父項/子項服務,也就是說,這與階層式隔離的安全原則不一致。
- 如要在拓撲中取代或模擬
LogSink/InspectSink,必須調整環境,這需要變更安全政策。 - 我們不是在「吃自己的狗食」嗎?第三方開發人員無法將環境用於通訊協定的任意用途,我們為什麼可以?
將 LogSink 和 InspectSink 設為架構功能
允許使用這些通訊協定 from: framework。封存管理員可以向架構公開這些功能,也可以與元件管理服務簽訂合約,提供這些功能。
優點:
- 與上一個替代方案的優點相同,但即使不是由元件管理服務提供服務,診斷通訊協定 (
InspectSink和LogSink) 也會成為架構通訊協定。 - 由於每個元件都有自己的一組專屬架構功能,因此架構會直接進行歸因,不需要能力歸因。
缺點:
- 缺點與上一個替代方案相同。
- 架構中使用的通訊協定第一個執行個體,並非由元件管理服務 直接提供。
- 不清楚如何在測試中提供獨立記錄,而不需額外建構供 Test Manager 使用的機制。
- 為所有元件 (包括裝置) 建立單一記錄目的地。
自動向所有孩子提供 cmc 優惠 LogSink
系統不會要求使用者在 CML 中新增 OfferDecl,而是會為每個子項和集合自動執行這項操作。cmc
優點:
- 明確的父項/子項產品,有助於模擬、取代拓撲中的通訊協定等。
- CML 沒有變更。
缺點:
- CMC 中能力的特殊處理方式。
- 在
.cml中宣告的元件與透過Realm/CreateChild建構的元件行為不一致。
在 cmc 中提供選項,並在 CML 中提供語法糖,可讓這項功能更具彈性,並提供其他機制可供利用,不只用於診斷。
不採取任何行動,照常轉接
開發人員必須手動為所有子項提供 LogSink 和 InspectSink。
優點:
- 明確的父項/子項產品,有助於模擬、取代拓撲中的通訊協定等。
- API 邊界仍是父項和子項之間的本地問題,不會涉及其他當事人。
缺點:
- 目前的問題:很容易錯過路由 LogSink,導致偵錯測試時浪費時間。
- 其他問題:很容易會錯過將路由
InspectSink傳送至某些元件 (因為現在每個人都能公開),導致缺少現場診斷資訊。這與 LogSink 的問題相同,因此現在我們有兩個通訊協定,而非只有一個。
由於這些通訊協定廣為使用,我們認為在 cmc 和 CML 中新增其他選項,有助於降低遺漏路徑的機率。
其他建議
其他討論的想法包括使用能力套件來傳送包含兩種通訊協定的套件,或以網域或能力來源的形式改善環境。diagnostics由於我們打算審查路由 API,因此捨棄了這些提案,改用現有機制和 API 提供的短期解決方案。
既有技術和參考資料
不適用