RFC-0168:通过 InspectSink 公开检查

RFC-0168:通过 InspectSink 公开 Inspect
状态已接受
区域
  • 诊断
  • 组件框架
说明

定义组件公开 Inspect 的机制。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2022-05-17
审核日期(年-月-日)2022-06-15

摘要

此 RFC 介绍了 fuchsia.diagnostics.InspectSink 协议,该协议允许组件公开 Inspect 数据。因此,现在可以移除当前机制(DirectoryReady 事件)了。

设计初衷

目前,Inspect 是通过与常规组件框架功能路由不一致的机制公开的。目前,组件会将其传出命名空间中的 diagnostics 目录公开给框架。

为了在 SDK 中发布事件功能,DirectoryReady 事件已在 RFC-121 中被标记为已废弃。不过,我们尚未找到一个理想的解决方案,来解决如果此目录不存在,组件如何公开 Inspect 数据的问题。此外,Flutter on Fuchsia 还希望消除对这些文件系统抽象的依赖,并简化其实现。重新思考组件如何公开 Inspect 将有助于它们消除大量运行时复杂性,并为开发者的人体工学带来优势。

利益相关方

教练:leannogasawara@google.com

Reviewers:

  • crjohns@google.com
  • geb@google.com
  • shayba@google.com

咨询了

  • dworsham@google.com
  • surajmalhotra@google.com
  • zarvox@google.com

共享:此 RFC 之前以 Google 文档的形式在诊断、组件框架、Flutter 等团队之间共享。

设计

背景

以前,归档程序通过 /hub 提取 Inspect 数据。其代码库的结构为中心上的目录监视器,这些监视器会在 out/diagnostics 目录出现(当时的名称有所不同)时开始跟踪组件的 Inspect 数据。此方法最终被移除,改为通过事件(在 appmgr 和组件管理器中)进行。此外,当时读取 Inspect 数据的测试是通过直接从 /hub 读取来实现的。

归档程序目前依赖于 DirectoryReady 事件来执行以下两项操作:

  • 从组件(组件 expose /diagnostics to framework)提取 Inspect 数据。
  • 将检查数据归因于源组件。

DirectoryReady 事件可解决这两点。不过,我们已经有了 CapabilityRequested 来处理 (2),并且作者认为我们可以使用常规协议(类似于 fuchsia.logger.LogSink)来处理 (1),从而获得额外优势。

解决归因问题并非本 RFC 的目标。我们将在日后移除目前用于 LogSinkDebugDataCapabilityRequested 事件。

InspectSink

此 RFC 介绍了 InspectSink 协议,该协议允许归档程序从组件提取 Inspect 数据。此协议定义如下:

library fuchsia.diagnostics;

using zx;

@discoverable
protocol InspectSink {
    /// Publishes a handle to the `fuchsia.inspect.Tree` protocol that the server can use to read
    /// Inspect data, including lazy nodes.
    Publish(struct {
        tree fuchsia.inspect.Tree;
        root zx.handle:<VMO, zx.rights.BASIC | zx.rights.READ | zx.rights.MAP, optional>;
    });

    /// Publishes a read handle to the inspect VMO  that the component asynchronously updates.
    /// The server can read Inspect using the Inspect reader algorithm [1]. A component using this
    /// method to publish Inspect won't be able to expose lazy nodes.
    ///
    /// [1]: /docs/reference/platform-spec/diagnostics/inspect-vmo-format.md#reader_algorithm
    PublishVmo(struct {
        name string;
        root zx.handle:<VMO, zx.rights.BASIC | zx.rights.READ | zx.rights.MAP>;
    });
}

主要方法是 Publish,大多数组件都将使用它,因为 fuchsia.inspect.Tree 是公开 Inspect 的标准方式。不过,我们提供了一种机制,允许组件仅发布 Inspect VMO。我们之所以需要这样做,原因有以下几点:

  • 如果组件不需要成为服务器,则无需成为服务器(没有理由运行异步循环,只使用功能,不提供任何内容),但仍应能够公开 Inspect。
  • 在驱动程序迁移为使用 fuchsia.inspect.Tree 之前(问题),它们将继续公开 VMO。
  • 在 Inspect Dart 库支持 fuchsia.inspect.Tree 之前,它需要继续公开 VMO。

fuchsia.logger.LogSink 一样,此协议将由归档程序提供并路由到组件。

与提供 out/diagnostics 目录相比,此协议具有以下几点优势:

  1. 与标准组件协议路由保持一致:

    • 组件只需使用协议 fuchsia.inspect.InspectSink,而无需执行 expose /diagnostics to framework,这与组件当前导出日志和轨迹的方式类似。
    • 归档管理员可以通过 CapabilityRequested 接收与其相关联的连接,从而保持归因。
  2. 您可以在启动组件异步循环之前提供检查数据。

    • 目录由 fuchsia.io.Directory 支持,大多数组件在启动异步循环之前不会提供其 out 目录。通过使用此协议,快照可以包含尚未启动异步循环但已写入 Inspect 数据的组件的 Inspect 数据。

    • fuchsia.inspect.Tree 协议也是如此。只有在组件开始处理此协议后,快照中才会显示组件的 Inspect 数据。在大多数情况下,除非组件开始其异步循环,否则不会发生这种情况。通过使用上述协议,我们可以立即向归档程序提供根 VMO(因此至少此 VMO 会包含在快照中),以及 fuchsia.inspect.Tree 的句柄以供日后请求。

  3. 不再有运行程序和文件系统实现方面的问题。

    • 我们目前在 appmgr 和组件管理器中添加了一些代码,用于对组件未按时分发 out/diagnostics 的情况进行特殊处理,而 Flutter 运行程序就是这种情况。该运行程序会先提供 out/ 目录,然后再填充该目录。理想情况下,我们只会使用目录监视器,但并非所有 VFS 实现都实现了监视器(尤其是 Flutter 使用的 C++ SDK 中的 VFS 实现),并且我们无法依赖于使用完整 fuchsia.io.Directory 实现的未来运行程序。

您可以在后台进行此更改,方法是更改 inspect/client.shard.cml 以使用新协议,而不是将诊断目录公开给框架。文件 inspect/client.shard.cml 通过 SDK 提供,所有公开“随时随地检查”功能的组件都会使用该文件。

此提案适用于 v2 组件。出于兼容性考虑,我们仍会处理 v1 组件的 out/diagnostics。由于我们正在逐步迁移到 v2,作者认为不值得花时间更改 v1 的运作方式。目标是在后台进行此更改,以便迁移到 v2 的组件无需更改其公开 inspect 的方式的代码。

实现

我们将遵循标准的 LSC 流程。

具体步骤如下:

  1. 在归档程序中实现新协议 InspectSink
  2. 使用 inspect/client.shard.cml 识别组件,并将 fuchsia.inspect.InspectSink 从归档程序路由到这些组件。目前,这会导致必须在 cml 定义中完全枚举所有此类组件的问题,但我们已经提出了解决方案,并将在后续的 RFC 中进行介绍。
  3. 更改 inspect/client.shard.cml 以使用此协议,并将 /diagnostics 目录公开给框架,从而实现平滑过渡。
  4. 支持连接到 InspectSink,而不是在 Inspect 库中公开 diagnostics 目录。
  5. 移除组件管理器中的 DirectoryReady 实现,并在所有组件都完成转换且所有预构建内容都已刷新后,从 fuchsia.sys2.Event 定义中移除 DirectoryReady。我们将根据 CTF 测试和支持期限来确定何时可以完成此操作。

性能

由于我们不再需要遍历目录或创建 DirectoryReady 事件,只需依赖单个协议,因此性能应该会有所提升。

安全注意事项

此更改符合组件框架安全属性,尤其是最小权限原则和分层隔离原则。

隐私注意事项

隐私权方面没有任何变化。被检查的数据会继续通过常规隐私保护流水线。

测试

此 RFC 的实现将通过以下方式进行测试:

  • 连接到 InspectSink 的库中的单元测试。
  • 在 Archivist(用于 InspectSink)中进行了单元测试和集成测试。
  • CTF 测试,用于检测兼容性变更。

文档

检查发现和托管将会更新。

目标是在后台的写入检查库中进行此更改。不过,如果我们最终要求在组件迁移到 v2 时进行代码更改,我们会在迁移指南的“诊断”部分反映这些更改。

缺点、替代方案和未知情况

一个适用于日志和检查的协议

我们可以使用 DiagnosticsSink,让组件能够在一个位置连接 Inspect 和日志。

  • 优点:只需路由单个协议,而不是 2 个协议。
  • 缺点:如果日后出于某种原因,我们需要对日志或“检查”进行不同的处理,那么如果我们为这两者维护不同的协议,可能比为这两者使用相同的协议更容易实现。

我们认为,由于日志和“检查”是不同的东西,因此这种替代方案的缺点使其非常不受欢迎,因此最好将它们单独路由。

在先技术和参考文档

不适用