检查发现和托管情况

检查是 Fuchsia 组件的一项强大的诊断功能。

本文档详细介绍了组件如何托管其 Inspect 数据,以及各种工具如何发现这些数据。

托管检查数据

组件可能会通过以下方式公开 Inspect 数据:

组件无需与其他服务联系即可公开 Inspect 数据。

组件通常无需关心使用的是哪种方法,客户端库会提取出托管的具体机制。几乎所有实现最终都会使用 Tree

功能 fuchsia.inspect.Tree VmoFile fuchsia.inspect.deprecated.Inspect 说明
非延迟值 组件可以记录字符串和整数等值。
延迟值 组件可能会在读取时动态生成值。
可变树 组件可能会修改其输出中存储的值。
事后检查 组件记录的值在该组件退出后可用。
低延迟快照 可以低延迟地获取数据的完整快照。
一致的快照 是* 树的快照保证代表其在某个时间点的状态。

(*:每个树的快照是一致的,但无法保证树间一致性)

fuchsia.inspect.Tree

fuchsia.inspect.Tree 支持 Inspect API 的所有功能,是从组件公开 Inspect 数据的推荐方式。

组件使用 fuchsia.inspect.InspectSink 协议发布 fuchsia.inspect.Tree

实现

fuchsia.inspect.Tree FIDL 文件定义了组件托管的协议,以公开其 Inspect 数据。

Tree 协议会将多个 Inspect VMO 以“树的树”的形式关联起来。

图:树的示例

在上图中,名为“root”的树会处理 fuchsia.inspect.Tree 下托管的顶级服务的连接协议 fuchsia.inspect.Tree。您可以使用该协议的方法枚举和打开子树。例如,“子 B”在打开并读取之前可能不存在于内存中。

该协议通过以下方式支持此行为:

  • GetContent

    此方法会获取树的内容,目前的形式为 Inspect VMO。根据惯例,对根树调用此方法应返回一个 VMO,该 VMO 将不断更新为新数据。客户端无需重新读取树的内容即可读取新值。

  • ListChildNames

    此方法接受一个迭代器,系统会通过该迭代器返回树的子级名称。例如,上图中的树在根树上运行时,将返回名称“child A”和“child B”。

  • OpenChild

    此方法接受对 fuchsia.inspect.Tree 的请求,该请求将绑定到由给定名称指定的树。使用此方法,客户端可以迭代通过根接口公开的所有树。

fuchsia.inspect.deprecated.Inspect

Go 使用此已废弃的接口来公开 Inspect 数据。虽然 fuchsia.inspect.Tree 会公开“树的树”,但此接口只会公开一个树,其中可以动态实例化子树。

此接口已废弃,取而代之的是 Inspect 树托管的 VMO 格式,原因如下:

  • VMO 格式支持低延迟快照,而无需与托管程序通信。
  • VMO 格式快照始终与整个树保持一致。
  • VMO 格式支持事后检查,使用已废弃接口的所有 Inspect 数据都会随组件一起失效。
  • Tree 协议支持与已废弃的接口相同的动态功能。

读取检查数据

读取检查数据的主要方式有两种:

  1. iquery
  2. 归档员

iquery

iquery(检查查询)是用于与检查数据进行交互的 CLI。

iquery 的主要操作模式是接受用于检查数据的选择器列表,并输出其中包含的信息。选择器由三个部分组成,以 : 分隔:

  1. 组件选择器:这是 v2 中的标识符,或 v1 中的 realm 路径和组件名称。
  2. 节点路径:检查层次结构中节点的路径。
  3. 属性路径:属性的名称。

对于 iquery,只有 (1) 是必需的。如果仅提供 (1)(例如 realm/component),则 iquery 将使用选择器 realm/component:* 提取所有检查数据。

iquery 包含两个实用程序命令,用于了解可用的组件和可使用的选择器:

  • list:iquery 将输出所有可用的组件选择器,即所有 v2 标识符和包含组件名称的所有 v1 领域路径。
  • selectors:iquery 将输出在所提供选择器位置下可用的所有选择器。

这些模式可以组合使用,如下所示:

$ iquery show `iquery list | grep component_name`

或者,iquery 还允许在某个位置输出检查数据。位置由 .inspect 文件的路径或包含 fuchsia.inspect.Tree 的目录的路径组成。iquery 包含一个实用程序命令,用于列出包含检查数据 (list-files) 的所有文件。

iquery 的辅助操作模式(由 list-files 触发)会从给定目录路径递归识别 Inspect 数据的位置。这两种模式可以结合使用,如下所示:

$ iquery list-files [component_moniker]
bootstrap/driver_manager
  class/display-coordinator/000.inspect
  ... additional output


$ iquery show --file 'class/display-coordinator/000.inspect'

在上面的示例中,系统会运行 iquery list-files 来查找“检查”位置列表。然后,系统会对其中一个输出运行 iquery,以递归方式列出匹配位置中的数据。您可以改为编写以下代码:

$ fx iquery show --component component_name

归档员

Fuchsia 诊断平台由 Archivist 托管,负责按需监控和汇总 Inspect 数据。

在组件管理器下运行时,系统会通过事件功能将诊断数据提供给归档程序。

归档管理员会收到根令牌网域提供的事件。因此,它会看到来自整个系统的事件。它可以查看和订阅的事件如下:

  • CapabilityRequested:当组件连接到 InspectSinkLogSink 时,发送到归档管理器,而不是常规目录连接。这样,Archivist 就可以知道连接到这些协议的组件的标识名和网址。

若要公开“检查”功能,组件需要使用 fuchsia.inspect.InspectSink 协议。组件通常会将 diagnostics 字典路由到它们,因此这通常如下所示:

{
    use: [
        {
            protocol: "fuchsia.inspect.InspectSink",
            from: "parent/diagnostics",
        },
    ],
}

有一个实用的清单包含项可简化此过程,并且 Inspect 库需要此项:

{
    include: [
        "inspect/client.shard.cml",
    ]
}

如果某个组件没有路由到它的 diagnostics 字典,并且该组件仅有路由到它的协议,那么使用该组件通常如下所示:

{
    use: [
        {
            protocol: "fuchsia.inspect.InspectSink",
            from: "parent",
        },
    ],
}

从归档员处读取 Inspect

归档程序托管 fuchsia.diagnostics.ArchiveAccessor,该服务提供 StreamDiagnostics 方法,用于从正在运行的组件获取 Inspect 数据。