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

RFC-0171:改善診斷轉送功能
狀態已接受
區域
  • 診斷資料
  • 元件架構
說明

CML 和 CMC 公用程式簡介診斷資訊轉送功能

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

摘要

提議將 cmc 和 CML 中的公用程式簡化為樹狀結構中任何診斷通訊協定 (fuchsia.logger.LogSinkfuchsia.diagnostics.InspectSink) 的轉送,並減少遺漏記錄檔或檢查資料的 DX 問題點。雖然本文著重介紹檢查和記錄,但也可用來改善大多數元件可能可用的其他通訊協定 (例如 fuchsia.tracing.provider.Registry) 的可用性。

提振精神

使用記錄檔的 DX 問題點,是元件必須在實際工作環境元件、測試、RealmBuilder 路徑等處,將 fuchsia.logger.LogSink 轉送到任何地方。記錄檔是大部分 Fuchsia 體驗中,幾乎所有元件和測試使用的核心部分。

RFC-0168 建議使用通訊協定 fuchsia.inspect.InspectSink 提議,允許元件發布檢查功能,進而改善部分效能並減少技術負債。和 fuchsia.logger.LogSink 一樣,我們希望所有 (或最多) 元件都使用「檢查」檢測功能。目前每個元件都可以 expose /diagnostics to framework,讓每個元件都能公開檢查,並提供給 Archivist 使用。改用通訊協定之後,我們必須確保所有元件都能繼續公開 Inspect 資料,這對開發人員偵錯其元件在執行階段執行的作業。

這屬於非人體工學且容易出錯,因為我們需要更新所有 CML,將這個通訊協定手動轉送至目前正在編寫檢查的所有元件。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.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 中的所有元件。此外,它會將 void 中的 Inspect/LogSink 優惠新增至 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 是元件擁有的集合和子項總數。

僅針對上一節所述的新選用引數中定義的通訊協定,系統會限制具有目標 allOfferDeclcmc 中使用。

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 陳述式並非免人工管理,因為其為語法糖,僅擴充為 OfferDecls。

為方便起見,我們將提供包含兩個 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 遷移至完整的優惠組合為止。
  4. 更新樹狀結構外的 cmc 用法,以使用新標記,並更新可能缺少路徑的現有 CML (利用優惠資料分割)。
  5. 更新 GN 和 Bazel SDK,以便要求診斷通訊協定。
  6. 加入 syslog/client.shard.cmlsyslog/offer.shard.cml
  7. 推出之後,重構使用優惠資料分割但不再需要的 OOT 資訊清單,因為其中包含在用戶端資料分割中。

效能

cmc 會執行一些額外工作,但應該不會對編譯時間造成任何重大影響。

安全性考量

此變更符合元件架構安全性屬性,特別是最低權限原則和階層隔離原則。

隱私權注意事項

不影響隱私權。

測試

新的「cmc」功能會進行單元測試。

說明文件

cmc 將會更新,加入新選項,並更新 CML 來描述新的 offer to all 功能。

缺點、替代方案和未知

Environment 中使用 debug_capabilities

這就是主要的替代方案。在此替代方案下,我們會擴充 fuchsia.sys2.Environmentdiagnostics_capabilities 使用類似 debug_capabilities 的方式,或是將 debug_capabilities 轉換成 diagnostics_capabilities,或只使用 debug_capabilities 進行診斷通訊協定,以供樹狀結構 from: diagnosticsfrom: debug 中的任何元件使用。

這項功能在元件管理服務安全性政策中會受到管制,確保這項功能只會由根架構師和嵌入測試中的 Archivist 使用。

優點

  • 每個元件都可以在樹狀結構中的任何位置使用 InspectSinkLogSink
  • 與世界目前的狀態對齊,其中每個元件都可以公開檢查項目。
  • 改善 DX,因為開發人員不需要花時間找出元件未記錄的原因,進而找出測試中缺少優惠的原因。
  • 以靜態方式檢查能力的點使用情形。
  • 除非明確使用此能力,否則所有元件皆以「nothing」開頭。
  • 包含透過 fuchsia.component.Realm/CreateChild 建立的動態元件。

缺點

  • 沒有其他明確的父項子項關係,也就是說,這不符合階層隔離的安全性原則。
  • 在拓撲中取代或模擬 LogSink/InspectSink,需要調整需要變更安全性政策的環境。
  • 我們沒有為了自己的通訊協定而使用環境,為什麼第三方開發人員無法利用環境做為通訊協定。為什麼呢?

提供 LogSinkInspectSink 架構功能

允許使用這些通訊協定 from: framework。Archivis 可將這些功能向架構公開,或是 Archivist 和元件管理服務之間需簽訂合約以提供這些功能。

優點

  • 與先前的替代方案相同,詳細說明診斷通訊協定 (InspectSinkLogSink) 成為架構通訊協定,即使元件管理員未透過元件管理員提供也沒問題。
  • 這個 API 不需要能力歸因,因為每個元件都會在架構中直接執行,因為每個元件都會取得一組專屬的架構功能。

缺點

  • 效果與先前替代方案相同。
  • 未由元件管理服務直接提供的架構使用的通訊協定執行個體:本身。
  • 不清楚如何在測試中提供隔離的記錄檔,而不建立測試管理員要使用的其他機制。
  • 為所有裝置元件建立單一記錄目的地。

cmc 自動為所有兒童提供 LogSink

相較於要求使用者將 OfferDecl 新增至 CML 的旗標,cmc 會自動為每個子項和集合執行此操作。

優點

  • 明確的父項-子項服務,可協助模擬、取代拓撲中的通訊協定等。
  • CML 沒有任何變更。

缺點

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

cmc 中提供選項和 CML 語法糖,這樣不僅更有彈性,也能提供其他人可利用的機制,而不只是用於診斷。

不像往常一樣規劃路線

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

優點

  • 明確的父項-子項服務,可協助模擬、取代拓撲中的通訊協定等。
  • API 邊界仍是父項和子項之間的本機疑慮,而不是涉及其他各方的疑慮。

缺點

  • 目前問題:很容易錯過 LogSink 資訊,導致在測試偵錯時遺失時間。
  • 其他問題:很容易將 InspectSink 轉送至某些元件 (因為現在所有人都可以公開這個元件),導致欄位中缺少診斷。這跟 LogSink 的問題相同,現在我們採用兩個通訊協定,而非只有一個通訊協定。

鑒於這些通訊協定的使用率,我們認為在 cmcCML 中新增其他選項,有助於降低遺漏路線的可能性。

其他建議

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

先前的圖片和參考資料