RFC-0171:改善診斷轉送功能

RFC-0171:改善診斷作業路徑
狀態已接受
區域
  • 診斷
  • 元件架構
說明

推出 CML 和 CMC 公用程式,改善診斷轉送

問題
Gerrit 變更
作者
審查人員
提交日期 (年-月-日)2022-05-19
審查日期 (年-月-日)2022-06-23

摘要

這項提案建議在 cmc 和 CML 中提供公用程式,以簡化樹狀結構中所有位置的診斷通訊協定 (fuchsia.logger.LogSinkfuchsia.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.LogSinkfuchsia.diagnostics.InspectSink

如要完全停用這項檢查功能,無論資訊清單如何呼叫 cmc,開發人員都可以在 CML 檔案中加入以下內容 (這是 CML 中推出的新語法):

{
    disable: {
        must_use_protocol: [ "fuchsia.logger.LogSink", "fuchsia.diagnostics.InspectSink" ],
        must_offer_protocol: [ "fuchsia.logger.LogSink", "fuchsia.diagnostics.InspectSink" ],
    }
}

如果開發人員不想將 LogSinkInspectSink 導向部分子項,可以自由選擇以下做法:

  • 使用能力路徑:將通訊協定 from: "void" 路由至他們想要關閉單一商品的子項/集合。
  • 手動將通訊協定從所需來源轉送。

這些功能的來源 bootstraproot 領域需要特殊處理:

  • bootstrap:這個選項會開啟,確保 LogSink 會轉送至 Bootstrap 中的所有元件。此外,也會將優惠 Inspect/LogSinkvoid 新增至 Archivist。
  • root:這個選項會開啟,確保我們將 LogSink 從 Archivist 轉送至所有同層兄弟姊妹。由於 bootstrap 是提供這項能力的服務,我們會從 void 新增 Inspect/LogSinkbootstrap

我們希望透過這項功能,讓 Fuchsia 上的每位開發人員都不會錯過記錄或檢查資料。

zarvox@ 為這個部分建立了原型 (和關聯鏈結)。

允許在 CML 中為所有子項和集合提供能力

為改善轉送至所有子項的 DX,我們會在 CML 中導入語法糖,讓您將能力轉送至「所有子項和集合」。

您可以使用以下語法糖果:

offer: [
    {
        protocol: "fuchsia.logger.LogSink",
        from: "parent",
        to: "all",
    }
]

當含有該語法的 CML 檔案編譯時,系統會產生 N 個 OfferDecl,其中 N 是元件擁有的集合和子項總數。

目標為 allOfferDecl 會在 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.cmlsyslog/offer.shard.cml
  • inspect/client.shard.cml:包含 inspect/use.shard.cmlinspect/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;
    

實作

  1. 更新 cmc,以便支援 CML 中的新標記和 offer to all
  2. 新增包含 offer LogSink to allsyslog/offer.shard.cml
  3. 更新樹狀結構中的 cmc 用法,以便使用新旗標,並更新可能缺少路徑的現有 CML。系統會更新 GN 和 Bazel SDK,但在 OOT CML 遷移至完整的產品組合之前,這些 SDK 的必要通訊協定預設為 []
  4. 更新樹狀結構中的 cmc 用法,以便使用新旗標,並更新可能缺少路徑的現有 CML (利用優惠分片)。
  5. 更新 GN 和 Bazel SDK,要求使用診斷通訊協定。
  6. 納入 syslog/client.shard.cml 中的 syslog/offer.shard.cml
  7. 推出後,請重構使用商品分片但不再需要該分片的 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: diagnosticsfrom: debug 中的任何元件都能使用。

這項功能會在元件管理服務安全性政策中設下限制,確保只有根目錄 Archivist 和測試中嵌入的 Archivist 才能使用。

優點

  • 每個元件都可以在樹狀結構的任何位置使用 InspectSinkLogSink
  • 與目前的全球狀態保持一致,每個元件都能公開檢查功能。
  • 開發人員不必花時間找出元件未記錄的原因,進而發現測試中缺少了廣告,因此可改善使用者體驗。
  • 可靜態檢查能力的點對點用法。
  • 除非明確使用此能力,否則所有元件在命名空間中都會以「nothing」開頭。
  • 涵蓋透過 fuchsia.component.Realm/CreateChild 建立的動態元件。

缺點

  • 不再提供明確的父項子項,這表示這項功能不符合階層隔離的安全性原則。
  • 在拓撲中取代或模擬 LogSink/InspectSink 需要調整環境,而這需要變更安全政策。
  • 這不是自食其力的最佳例子嗎?第三方開發人員無法將環境用於其通訊協定的任意用途,我們為何要這麼做?

製作 LogSinkInspectSink 架構功能

允許使用這些通訊協定 from: framework。Archivist 可以將這些功能公開給架構,也可以在 Archivist 和元件管理服務之間建立合約,以便提供這些功能。

優點

  • 優點與前述替代方案相同,但詳細說明診斷通訊協定 (InspectSinkLogSink) 會成為架構通訊協定,即使未由元件管理服務提供服務也一樣。
  • 由於每個元件都會取得專屬的一組架構功能,因此不需要指派能力,因為指派作業會直接在架構中執行。

缺點

  • 與前述替代方案相同的缺點。
  • 從框架使用的通訊協定第一個例項,此框架並非由元件管理服務本身提供。
  • 不清楚如何在測試中提供獨立的記錄,而無須建立供 Test Manager 使用的額外機制。
  • 為所有裝置端元件建立單一記錄目的地。

cmc 自動為所有孩子提供 LogSink

cmc 會為每個子項和集合自動執行這項操作,而非使用標記要求使用者將 OfferDecl 新增至 CML。

優點

  • 明確的父項/子項產品,可協助模擬、取代拓樸中的通訊協定等。
  • CML 沒有任何變更。

缺點

  • 在 CMC 中對某項能力採取特殊處理。
  • .cml 中宣告的元件和透過 Realm/CreateChild 建構的元件行為不一致。

cmc 中提供選項,並在 CML 中提供語法糖,可讓這項功能更具彈性,並提供可供他人利用的機制,而不僅限於診斷。

不採取任何行動,並照常轉送

請開發人員手動為所有子項提供 LogSinkInspectSink

優點

  • 明確的父項/子項產品,可協助模擬、取代拓樸中的通訊協定等。
  • API 邊界仍是父項和子項之間的本地問題,而非涉及其他方的邊界。

缺點

  • 目前的問題:很容易遺漏 LogSink 路由,導致在偵錯測試時浪費時間。
  • 其他問題:很容易錯過將 InspectSink 路由至某個元件 (因為目前每個人都可以公開),導致在欄位中遺漏診斷資訊。這與 LogSink 遇到的問題相同,因此我們現在在兩個通訊協定中都遇到這個問題,而非只有一個。

考量這些通訊協定的廣泛使用情形,我們認為在 cmcCML 中新增其他選項,有助於降低遺漏路徑的可能性。

其他想法

我們也討論了其他想法,例如使用能力套件來路由包含兩種通訊協定的 diagnostics 套件,或是以網域或能力來源的形式改善環境。由於我們計畫審查路由 API,因此捨棄了這些方案,改用採用現有機制和 API 的短期解決方案。

既有技術與參考資料