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
,讓元件發布 Inspect,以便進行一些改善並減少技術債務。就像 fuchsia.logger.LogSink
一樣,我們希望所有 (或至少大多數) 元件都使用 Inspect 檢測功能。目前,每個元件都可以 expose /diagnostics to framework
,讓每個元件都能公開檢查功能,並提供給 Archivist 使用。我們必須朝向通訊協定邁進,確保所有元件都能繼續公開檢查資料,這對開發人員來說非常重要,可用於偵錯元件在執行階段執行的作業。
這不符合人體工學,且容易出錯,因為我們需要更新所有 CML,才能手動將這個通訊協定路由至目前正在寫入檢查資訊的所有元件。LogSink
也存在相同的問題,尤其是在測試中,很容易忘記將 LogSink
路由至測試中的元件,導致記錄遺失,並浪費開發人員的時間。
元件管理服務會利用元件的 LogSink
列印與該元件相關的路由錯誤。這可改善 DX,因為開發人員可以快速找出路由錯誤。不過,如果 LogSink
未正確轉送,這些錯誤就會出現在歸因於元件管理服務的全域 syslog,開發人員更容易錯過這些錯誤,因為他們會查看自己的元件記錄。
本文件嘗試在 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
的對等項目。
每當呼叫 cmc
時,系統都會更新 GN 和 Bazel 工具,以便在這些選項中傳遞 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
會轉送至 Bootstrap 中的所有元件。此外,也會將優惠Inspect
/LogSink
從void
新增至 Archivist。root
:這個選項會開啟,確保我們將LogSink
從 Archivist 轉送至所有同層兄弟姊妹。由於bootstrap
是提供這項能力的服務,我們會從void
新增Inspect
/LogSink
至bootstrap
。
我們希望透過這項功能,讓 Fuchsia 上的每位開發人員都不會錯過記錄或檢查資料。
zarvox@ 為這個部分建立了原型 (和關聯鏈結)。
允許在 CML 中為所有子項和集合提供能力
為改善轉送至所有子項的 DX,我們會在 CML 中導入語法糖,讓您將能力轉送至「所有子項和集合」。
您可以使用以下語法糖果:
offer: [
{
protocol: "fuchsia.logger.LogSink",
from: "parent",
to: "all",
}
]
當含有該語法的 CML 檔案編譯時,系統會產生 N 個 OfferDecl
,其中 N 是元件擁有的集合和子項總數。
目標為 all
的 OfferDecl
會在 cmc
中設下門檻,僅可用於在前一個章節所述的新選用引數中定義的通訊協定。
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
(因為使用的是通訊協定),則分割區中的 offer to all
陳述式會是無操作,因為它是語法糖,只會如前所述展開為 OfferDecl
。
為了方便起見,我們會提供包含兩個 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 採用的方法不一致,但RealmBuilder
API 在某些方面已經偏離,以提供更方便的工作流程,更適合用於測試。我們預期 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 遷移至完整的產品組合之前,這些 SDK 的必要通訊協定預設為[]
。 - 更新樹狀結構中的
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
。 - 與目前的全球狀態保持一致,每個元件都能公開檢查功能。
- 開發人員不必花時間找出元件未記錄的原因,進而發現測試中缺少了廣告,因此可改善使用者體驗。
- 可靜態檢查能力的點對點用法。
- 除非明確使用此能力,否則所有元件在命名空間中都會以「nothing」開頭。
- 涵蓋透過
fuchsia.component.Realm/CreateChild
建立的動態元件。
缺點:
- 不再提供明確的父項子項,這表示這項功能不符合階層隔離的安全性原則。
- 在拓撲中取代或模擬
LogSink
/InspectSink
需要調整環境,而這需要變更安全政策。 - 這不是自食其力的最佳例子嗎?第三方開發人員無法將環境用於其通訊協定的任意用途,我們為何要這麼做?
製作 LogSink
和 InspectSink
架構功能
允許使用這些通訊協定 from: framework
。Archivist 可以將這些功能公開給架構,也可以在 Archivist 和元件管理服務之間建立合約,以便提供這些功能。
優點:
- 優點與前述替代方案相同,但詳細說明診斷通訊協定 (
InspectSink
和LogSink
) 會成為架構通訊協定,即使未由元件管理服務提供服務也一樣。 - 由於每個元件都會取得專屬的一組架構功能,因此不需要指派能力,因為指派作業會直接在架構中執行。
缺點:
- 與前述替代方案相同的缺點。
- 從框架使用的通訊協定第一個例項,此框架並非由元件管理服務本身提供。
- 不清楚如何在測試中提供獨立的記錄,而無須建立供 Test Manager 使用的額外機制。
- 為所有裝置端元件建立單一記錄目的地。
讓 cmc
自動為所有孩子提供 LogSink
cmc
會為每個子項和集合自動執行這項操作,而非使用標記要求使用者將 OfferDecl
新增至 CML。
優點:
- 明確的父項/子項產品,可協助模擬、取代拓樸中的通訊協定等。
- CML 沒有任何變更。
缺點:
- 在 CMC 中對某項能力採取特殊處理。
- 在
.cml
中宣告的元件和透過Realm/CreateChild
建構的元件行為不一致。
在 cmc
中提供選項,並在 CML
中提供語法糖,可讓這項功能更具彈性,並提供可供他人利用的機制,而不僅限於診斷。
不採取任何行動,並照常轉送
請開發人員手動為所有子項提供 LogSink
和 InspectSink
。
優點:
- 明確的父項/子項產品,可協助模擬、取代拓樸中的通訊協定等。
- API 邊界仍是父項和子項之間的本地問題,而非涉及其他方的邊界。
缺點:
- 目前的問題:很容易遺漏 LogSink 路由,導致在偵錯測試時浪費時間。
- 其他問題:很容易錯過將
InspectSink
路由至某個元件 (因為目前每個人都可以公開),導致在欄位中遺漏診斷資訊。這與 LogSink 遇到的問題相同,因此我們現在在兩個通訊協定中都遇到這個問題,而非只有一個。
考量這些通訊協定的廣泛使用情形,我們認為在 cmc
和 CML
中新增其他選項,有助於降低遺漏路徑的可能性。
其他想法
我們也討論了其他想法,例如使用能力套件來路由包含兩種通訊協定的 diagnostics
套件,或是以網域或能力來源的形式改善環境。由於我們計畫審查路由 API,因此捨棄了這些方案,改用採用現有機制和 API 的短期解決方案。
既有技術與參考資料
無