贡献者:cphoenix@
此 Codelab 介绍了分类实用程序:
- 用途。
- 运行方式,包括命令行选项。
- 如何添加和测试配置规则以检测 Fuchsia 快照中的问题。
如需查看本文档所提及的源文件和示例,请访问以下网址:
- //examples/diagnostics/triage/snapshot/inspect.json。
- //examples/diagnostics/triage/rules.triage。
- //examples/diagnostics/triage/solution。
什么是分类?
通过分类,您可以扫描 Fuchsia 快照(snapshot.zip 文件)以检查预定义条件。
分类系统使您可以轻松配置新条件,从而提高分类功能的实用性。
前提条件
在开始学习此 Codelab 之前,请确保您已完成以下操作:
- 开始使用。
- 使用
fx build
创建了一个 Fuchsia build。
从命令行运行分类
- 如需运行分类,请执行以下操作:
fx triage
此命令会使用 fx snapshot
命令下载新的 snapshot.zip
文件。此命令会运行位于源代码树中的默认规则:
//src/diagnostics/config/triage/*.triage
如需分析特定 snapshot.zip 文件,请使用 --data
。
- 您最多可以指定一个
--data
参数。 --data
的参数也可以是包含解压缩快照的目录的路径。- 如果您在未指定
--data
选项的情况下运行fx triage
,它会运行新的fx snapshot
并分析其文件。
fx triage --data my/foo/snapshot.zip
如需使用特定配置文件或特定目录中的所有 *.triage
文件,请使用 --config
。
- 您可以使用多个
--config
参数。 - 如果使用了
--config
参数,则系统不会自动加载默认规则。
fx triage --config my/directory --config my/file.triage
添加分类规则
此 Codelab 的其余部分介绍了如何在 Triage 中配置新行为。
概览
分类功能通过以下步骤将大量诊断数据压缩为实用信息:
- 使用配置文件
select
部分中的 selector 字符串从inspect.json
文件中选择值。 - 执行计算和比较以生成新值,如配置文件的
eval
部分指定。 - 根据配置文件
act
部分中的条目采取措施。- 如果错误条件(布尔表达式)为 true,则发出警告。
- 向用户显示一个值。
- 支持通过
test
部分中的条目对操作和计算进行单元测试。
查找 Codelab 的示例文件
进入源代码树中的 examples/diagnostics/triage
目录。以下命令旨在从该目录运行:
fx triage --config . --data snapshot
在包含未经修改的 Codelab 文件的示例目录中运行此命令,会输出一行预先提供的操作:
Warning: 'always_triggered' in 'rules' detected 'Triage is running': 'always_true' was true
检查.json
此 Codelab 包含一个 inspect.json
文件,其中包含检查数据,以确保运动以可预测的方式运行。此文件位于 snapshot/inspect.json
下的示例目录中。
rules.triage
分类程序会使用从一个或多个 .triage 文件加载的配置。
此 Codelab 使用位于示例目录中的 rules.triage
文件。
.triage 文件使用 JSON5,后者比 JSON 更易于写入和读取:
- 在最后一个列表项后添加英文逗号是一种不错的样式。
- 大多数键(包括所有有效的分类名称)不需要用引号括起来。
- /* 可以使用多行 */ 和 // 单行注释。
为 Inspect 值添加选择器
示例目录中的 inspect.json
文件表明系统存在一些问题。您将配置分类系统以检测这些问题。
此步骤会将分类配置为从 inspect.json
文件中的数据中提取值。
rules.triage
文件包含一个名为 select
的键值对部分。每个键(名称)都可以在其他配置条目的正文中使用。每个值都是一个选择器字符串。实际上,select
部分(以及如下所述的 eval
部分)中的每个条目都定义了一个变量。
选择器字符串是以英文冒号分隔的字符串,告知可以在检查数据中的哪个位置查找所需的值。
select: {
disk_total: "INSPECT:bootstrap/fshost:root/data_stats/stats:total_bytes",
// "data_stat" is an intentional typo to fix later in the codelab.
disk_used: "INSPECT:bootstrap/fshost:root/data_stat/stats:used_bytes",
}
由组件发布的检查数据以节点树的形式进行组织,其值(属性)位于左边。inspect.json
文件是这些树的数组,其中每个树都有一个用于标识源组件的名称。
INSPECT:
和第二个冒号之间的选择器字符串部分应与 inspect.json
文件中的其中一个名字字符串匹配。
第二个和第三个冒号之间的部分是一系列以 /
分隔的节点名称。
最后一个冒号后面的部分是属性名称。
上述选择器字符串表示了一个组件,该组件的 moniker
与字符串 bootstrap/fshost
匹配,且其检查树包含路径 root/data_stat/stats
。并且还指明了该组件的检查树的 root
节点的 stats
子节点中的 used_bytes
属性。
将上述选择器放入 rules.triage 文件的“选择”部分。
生成选择器
手动输入选择器很容易出错,因此可以使用 fx triage --select
来输出有效的选择器。
fx triage --data snapshot --select total_bytes
INSPECT:bootstrap/fshost:root/data_stats/stats:total_bytes
可以使用多个 --select
参数。该程序将为快照的诊断数据生成所有可能的选择器,然后通过所有 --select
参数进行过滤 (grep)。
添加计算
从 inspect.json
文件中选择值后,您需要执行一些逻辑(可能还需要进行一些算术),以查看这些值是否表示值得标记的条件。
复制以下行并将其添加到 rules.triage
文件的 eval
部分,以计算磁盘已满的容量:
eval: {
....
disk_percentage: "disk_used / disk_total",
}
eval
条目使用普通中后缀数学表达式。如需了解详情,请参阅详细信息部分。
添加操作
在配置文件的“act”部分中,添加一个操作,用于在磁盘已满 98% 时输出警告。使用以下几行代码:
act: {
...
disk_full: {
type: "Warning",
trigger: "disk_percentage > 0.98",
print: "Disk reached 98% full",
},
}
请注意以下几点:
添加刻度盘图
act: {
...
disk_display: {
type: "Gauge",
value: "disk_percentage",
format: "percentage",
}
}
量表始终显示提供的值。
format
字段为可选字段。“percentage”值会告知输出格式化程序预期会获得介于 0 到 1 之间的值,并将其显示为百分比。
试试看
以下命令将针对本地配置文件运行分类。
fx triage --config . --data snapshot
您会收到一条类似如下所示的错误:
[ERROR] In config 'rules': No value found matching selector
bootstrap/fshost:root/data_stat/stats:used_bytes
选择器规则中存在拼写错误。分类无法找到评估规则所需的值。实际上,正确的选择器是“data_stats”,而不是“data_stat”。 请在选择器规则中修正此问题,然后重试。
fx triage --config . --data snapshot
现在发生了什么情况?什么都没有,对吧?那么,如何判断 inspect.json
文件中是不存在问题,还是规则存在 bug?
测试规则
您可以(并且应该!)为自己的操作添加测试。对于每个测试,请指定值,以及这些值是否应触发您的规则。
如需测试您添加的规则,请将以下代码添加到 rules.triage
文件的 test
部分:
test: {
....
is_full: {
yes: ["disk_full"],
values: {
disk_used: 98,
disk_total: 100,
}
}
}
values
部分中的键应为 eval
或 select
条目的名称。提供的值将覆盖该条目本应选择或计算的值。
您还可以测试不应触发操作的条件:
test: {
....
not_full: {
no: ["disk_full"],
values: {
disk_used: 97,
disk_total: 100,
}
}
}
只需运行 Triage 即可运行测试。每次运行时,它都会自动自测。
fx triage --config . --data snapshot
哎呀!这应表示发生错误:
Test is_full failed: trigger 'disk_percentage > 0.98' of action disk_full
returned Bool(false), expected true
修正规则
您希望在磁盘可用空间达到 98% 或更多时触发,但这并不在您写入的内容中,并且您的测试发现了问题。将您操作中的 >
修改为 >=
:
trigger: "disk_percentage >= 0.98",
再次运行 Triage。错误应该会消失,并替换为一条警告,提示您 inspect.json
文件实际上表示磁盘已满。
Warning: 'disk_full' in 'rules' detected 'Disk is 98% full': 'disk98' was true
日志文件扫描
您可以编写表达式来测试日志文件的某一行(syslog.txt、klog.txt、bootlog.txt)是否与正则表达式匹配。如下所示:
eval: {
syslog_has_not_found: "SyslogHas('ERROR.*not found')",
...
}
act: {
something_not_found: {
trigger: "SyslogHas('ERROR.*not found')",
...
}
}
函数包括 SyslogHas()、KlogHas()、BootlogHas()。如果缺少某个日志文件(例如,某些快照不包含 bootlog.txt),系统会将其视为空文件。
如需对此进行测试,您可以在测试中添加如下条目:
test: {
test_error: {
yes: [error_scan],
syslog: "ERROR: file Foo not found\nSecond line OK",
}
}
批注.json
快照包含一个文件 annotations.json
,其中包含有关 build、开发板、正常运行时间等的信息。
您可以通过将 Annotation()
函数与单个字符串参数(该文件中 JSON 对象的键)结合使用,从此文件中提取值。例如:
eval: {
using_chromebook: "Annotation('build.board') == 'chromebook-x64'",
}
使用多个配置文件
您可以添加任意数量的 Triage 配置文件,甚至可以使用在一个文件内的另一个文件中定义的变量。它有很多用途:
- 一个文件用于与磁盘相关的变量和操作,另一个用于与网络相关的变量和操作。
- 用于定义产品特定编号的文件。
- 为特定工程师或团队创建单独的文件。
添加一个包含以下内容的文件“product.triage”:
{
eval: {
max_components: "4",
},
}
请注意以下几点:
- .triage 文件中可以省略空白部分。此文件不包含任何
select
、act
或test
条目。 - 虽然 JSON 中的数值未加引号,但
4
是一个数学表达式字符串,因此需要加上英文引号。
将以下条目添加到 rules.triage 文件中:
select: {
...
actual_components: "INSPECT:bootstrap/archivist:root/event_stats:components_started",
}
这将提取出设备中的活动组件数量。
eval: {
...
too_many_components: "actual_components > product::max_components",
这会将实际分量与产品理论最大值进行比较。
最后,添加操作:
act: {
...
component_overflow: {
type: "Warning",
trigger: "too_many_components",
print: "Too many components!",
},
}
遗憾的是,此设备尝试使用的组件过多,因此在运行“fx 分类”时应触发此警告。
在生产环境中,可以在不同的目录中维护多个“product.triage”文件,并且可以指示 Triage 通过“--config”命令行参数使用其中的任何文件。
测试和命名空间
测试仅使用发生测试的文件中的指标,以及测试提供的值。使用命名空间型值(如“a::b”)的表达式(评估或测试触发器)必须具有由测试值中的“a::b”条目提供的这些值。
test: {
component_max_ok: {
no: [
"component_overflow",
],
values: {
actual_components: 17,
"product::max_components": 17,
},
},
},
详细信息
姓名
名称(选择器、表达式、操作、测试以及配置文件的基名)可以是任何字母或下划线,后跟任意数量的字母、数字或下划线。
在分类结构的未来版本中,以下划线开头的名称可能具有特殊含义。这些行为并未被禁止,但最好还是要避免。
每个 .triage 文件的名称都会确定其命名空间。不允许从不同目录加载两个同名的 .triage 文件。
数学表达式
- 变量可以是 64 位浮点数、有符号的 64 位整数或布尔值。
- 算术表达式使用
+ - * / //
运算符,具有普通的运算顺序和优先级。 - 除法运算符
/
会生成一个浮点值。 - 除法运算符
//
会生成一个 int 值,将结果截断至 0,即使使用浮点参数也是如此。(请注意,这与 Python 3 不同, Python 3 // 会向下截断。) + - *
会保留其操作数的类型(混合提升为浮点数)。- 比较运算符为
> >= < <= == !=
- 比较运算具有布尔值结果类型,可用于触发操作。
- 您可以在一条
eval
规则中结合使用计算和比较运算。 - 您可以使用括号。
- 您可以将
eval
和select
条目的键名用作变量。 - 空格在任何位置都是可选的,在
filename::variable
命名空间型变量内以外的任何位置都允许使用。
预定义函数
分类提供可在 eval
表达式中使用的预定义函数:
Max(value1, value2, value3...)
返回最大值,类型提升为浮点数。Min(value1, value2, value3...)
返回最小值,类型提升为浮点数。And(value1, value2, value3...)
接受布尔值参数并返回值的逻辑与 (AND)。Or(value1, value2, value3...)
接受布尔值参数并返回值的逻辑 OR。Not(value)
接受一个布尔值参数并返回其逻辑 NOT。- 如果相应的日志文件具有行匹配匹配器(即包含正则表达式的字符串),则
SyslogHas(matcher)
、KlogHas(matcher)
、BootlogHas(matcher)
会返回 true。 Annotation(key)
从 annotation.json 文件中返回相应的值。Option(value1, value2, value3...)
会返回第一个有用值以支持选择器迁移和默认值:第一个非空列表、非 Missing 值(如果有)或空列表(如果已提供);或者缺失。- 如果值是错误指示,
Missing(value)
会返回 true。 Days()
、Hours()
、Minutes()
、Seconds()
、Millis()
、Micros()
和Nanos()
会计算与单调时间戳进行比较的值。Now()
会返回创建诊断数据的大致时间戳。StringMatches(value, regex)
会将指定的正则表达式应用于指定值,如果存在匹配项,则返回 true。Rust 正则表达式 crate 支持正则表达式语法。
函数编程
分类可以将函数应用于值的矢量。矢量的格式为 "[expr, expr, expr...]"
。某些选择器会返回多元素向量。
分类提供函数 Map()
、Fold()
、Filter()
和 Count()
来处理矢量,Fn()
定义要应用的映射、折叠和过滤器的函数或 lambda,并提供 Apply()
来将 Fn() 应用到参数。
如需了解详情,请参阅配置 fx 分类。
延伸阅读
如需了解最新功能和选项,请参阅 fx triage
- 分类将不断改进!