概览
Fuchsia 中的诊断平台包含多个服务。这些服务(例如数据提取、指标轮询和错误状态分析)都有一个共同的需求,即描述其诊断数据的具体属性。
我们创建了一个名为“诊断选择器”的领域特定语言 (DSL),可用于描述组件公开的诊断属性。选择器旨在对诊断架构执行操作,并且在以下情况下会使用:
- 诊断数据编码为“数据层次结构”,其中命名节点同时托管子节点和命名诊断属性。
- 诊断层次结构可通过其标识符归因于公开相应数据的特定组件。
诊断选择器具有以下高级语法:
<component_selector>:<hierarchy_path_selector>:<property_selector>
上述语法的三个部分用于逐步编制 Fuchsia 诊断数据源的索引:
component_selector
:按提供方的标识名指定诊断数据的提供方。hierarchy_path_selector
:指定从(由生产者)公开的数据层次结构到感兴趣的特定节点的路径。property_selector
:指定您在层次结构中指定的节点上的感兴趣的具体属性。
基于诊断平台构建的一些工具(例如分类和检测)需要使用选择器来区分数据类型。这些工具通过指定数据类型的额外语法扩展了选择器 DSL:
INSPECT|LOG|LIFECYCLE:<component_selector>:<hierarchy_path_selector>:<property_selector>
下文详细介绍了该语法的各个部分。
作为文件
评论
诊断选择器可以写入平面目录中的 cfg 文件中。在这些文件中,可以使用 //
编写注释。例如,
// a comment
core/sessions/foo
core2/session:foo // inline comment
组件选择器
语法
组件选择器定义了一个模式,用于描述组件拓扑中一个或多个组件的标识名。组件选择器是一个由正斜杠 (/
) 分隔的字符串集合,用于描述从根组件到感兴趣的组件的路径。
以下组件拓扑用于演示组件选择器语法:
考虑以下拓扑中的组件选择器:
core/sessions/foo
此组件选择器可明确识别相对于其祖父级 core
的命名为 foo
的组件。
组件选择器的每个细分(以正斜线分隔的部分)仅描述组件拓扑的 1 个“层级”。
组件选择器细分只能包含组件标识名中接受的字符。每个组件选择器片段都是一个实例名称或包含实例名称的集合名称,其字符和长度受到限制。集合名称和实例名称之间的冒号 :
必须用反斜线 (\
) 转义。
通配符
组件选择器支持通配符,可匹配组件选择器的单个“层级”。请考虑以下 component_selector,它应用于上述示例拓扑:
core/other_comp/*
此选择器会匹配系统中在名为 other_comp
的父级下运行的所有组件,该父级本身在父级 core
下运行。它们的标识名如下:
core/other_comp/foo
core/other_comp/bar
通配符还可用作组件选择器的单个“层级”的字符串补全正则表达式。请参考上图,考虑以下组件选择器:
core/*_comp
这会匹配系统中在名为 core
的父级下运行且名称以 _runner
结尾的所有组件。其中包括以下标识名:
core/some_comp
core/other_comp
组件选择器可以以递归通配符 **
结尾,该通配符会与给定领域下的所有组件匹配:
core/**
这会匹配在 core
或 core
的任何子领域下运行的系统上的所有组件。
仅组件选择器 **
即可匹配系统上的所有组件。
层次结构路径选择器
语法
层次结构路径选择器用于定义一个模式,该模式描述了从结构化数据层次结构到一个或多个命名节点的路径。此子选择器的语法与组件选择器的语法几乎完全相同,因为它们都描述了通过命名节点树的路径。唯一的区别是下面介绍的可选树名称过滤条件。
请考虑以下诊断数据层次结构的 JSON 编码。在本例中,该层次结构来自“检查”。
"root": {
"reverser_service": {
"connection-0x0": {
"request_count": 1,
},
connection_validity: {
"is_valid": true
},
"connection_count": 1,
"connection_validity": "connection_xyz"
},
"version": "part1"
}
鉴于此数据层次结构,请考虑以下层次结构路径选择器:
root/reverser_service/connection-0x0
此层次结构路径选择器会明确描述从数据层次结构的根到数据层次结构中的特定节点的路径。
选择器的每个细分(由正斜杠分隔的部分)都仅描述数据层次结构的一级或一个节点。层次结构路径选择器段可能包含任何字符,但如果某个段需要包含星号 (*
)、正斜杠 (/
)、反斜杠 (\
)、空格(制表符 \t
或 )或英文冒号 (
:
),则必须对这些字符进行转义。
需要注意的是,在给定节点同时共享同名子项和属性的情况下,只有层次结构路径选择器(而非组件选择器)才会出现这种情况。请考虑以下选择器:
root/reverser_service/connection_validity
此路径层次结构选择器描述了从根目录到 connection_validity
节点的路径。它与 reverser_service
节点上的 connection_validity
属性完全无关,后者可以使用属性选择器进行选择:root/reverser_service:connection_validity
。
通配符
层次结构路径选择器支持通配符,可与组件选择器的单个“层级”匹配。以下示例将匹配数据层次结构中根目录下节点 reverser_service 的所有子节点:
root/reverser_service/*
通配符还可用作组件选择器的单个“层级”的字符串补全正则表达式。以下示例将匹配 reverse_service
下以 connection-
开头的所有节点。
core/reverser_service/connection-*
在上面的示例中,唯一匹配的节点是 connection-0x0
,但如果存在更多连接节点,它们也会匹配。
树名称过滤条件
当组件发布多个 fucshia.inspect.Tree
协议时,选择器语法支持按协议元数据中的 name
值过滤这些树。
假设您在执行 ffx inspect show core/my_component
时,Inspect 层次结构如下所示:
core/my_component:
metadata:
name = root
component_url = fuchsia-boot:///my_component#meta/my_component.cm
timestamp = 70863435581892
payload:
root:
connections:
connections_closed = 7
core/my_component:
metadata:
name = second_tree
component_url = fuchsia-boot:///my_component#meta/my_component.cm
timestamp = 70863435581892
payload:
root:
data:
values = [0, 1, 2]
如果您知道自己需要属性 root/data:values
,则可以使用树名称过滤条件,以避免对这两棵树进行快照的开销,具体语法如下(暂时忽略属性选择器部分):
[name=second_tree]root/data
如果您不知道要针对哪个树进行选择,或者知道要从所有树中进行选择,可以使用以下层次结构选择器:
[...]root
这相当于列出所有名称:
[name=root, name=second_tree]root
目前,如果省略列表,系统会将其视为等同于 [...]
,但这只是一个过渡阶段。如果您知道组件会导出多个名称不同的树,请优先使用显式语法。
如果组件在发布 Inspect 时未指定名称,则默认名称为 root
。此bug 会跟踪使省略的名称过滤条件列表等同于 [name=root]
的操作。
名称过滤条件列表中的值没有字符限制,但必须对 *
进行转义。如果名称包含 [a-zA-Z0-9-_]
以外的值,则必须将名称括在引号中。在带引号的名称中,必须对内部引号进行转义。
名称过滤条件区分大小写。
媒体资源选择器
语法
属性选择器是所有子选择器中最简单的。它定义了一个用于匹配单个字符串的模式,该字符串是诊断层次结构中的属性名称。诊断层次结构中的所有属性都有字符串名称。省略媒体资源选择器实际上就是使用层次结构路径选择器
与上一个选择器片段一样,如果您希望与星号 (*
)、正斜杠 (/
)、反斜杠 (\
)、空格(制表符 \t
或 )或英文冒号 (
:
) 进行匹配,则必须使用反斜杠 (\
) 对它们进行转义。
通配符
通配符可用于匹配整个属性字符串,也可以用作字符串补全 glob。
eg: abc will match any string with the exact name "abc".
eg: a\* will match any string with the exact name "a*".
eg: a\\* will match any that starts with exactly "a\".
eg: a* will match any string that starts with "a".
eg: a*b will match any string that starts with a and ends with b.
eg: a*b*c will match any string that starts with a and ends with c, with b in the middle.
完整选择器示例
以下选择器将从系统上存在于任何位于 realm1
下的领域中的任何 echo.cm
实例中选择数据。检索到的数据将是 a/b/c
节点上的 active_connections
属性。
realm1/*/echo:a/b/c:active_connections
以下选择器将选择系统中任何 echo.cm
实例中存在的任何领域(本身直接位于 realm1
下)中的检查数据。检查数据将是 a/b/c/d
节点上的 memory_usage property
。
realm1/echo:a/b/c/d:*