分类 Codelab

贡献者:cphoenix@

此 Codelab 介绍了分类实用程序:

  • 用途。
  • 运行方式,包括命令行选项。
  • 如何添加和测试配置规则以检测 Fuchsia 中的问题 快照。

有关本文档所参考的源文件和示例,请访问:

什么是 Triage?

借助分类功能,您可以扫描 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

如需使用特定配置文件或特定 API 中的所有 *.triage 文件,请执行以下操作: 目录中,请使用 --config

  • 您可以使用多个 --config 参数。
  • 如果使用 --config 参数,则默认规则将不适用 自动加载。
fx triage --config my/directory --config my/file.triage

添加分类规则

此 Codelab 的其余部分将介绍如何在 Triage 中配置新行为。

概览

分类功能可将海量诊断数据浓缩为实用信息, 执行下列步骤:

  1. 使用 selector 字符串从 inspect.json 文件中选择值 select 部分。
  2. 执行计算和比较以生成新值,如 配置文件的 eval 部分。
  3. 根据配置文件的 act 部分中的条目执行操作。
    1. 如果错误条件(布尔表达式)为 true,则发出警告。
    2. 向用户显示值。
  4. 支持通过 test 中的条目对操作和计算进行单元测试 部分。

查找 Codelab 的示例文件

导航到源代码树中的 examples/diagnostics/triage 目录。 以下命令将从该目录运行:

fx triage --config . --data snapshot

在包含未经修改的 Codelab 文件的示例目录中运行此命令 从预先提供的操作输出一行代码:

Warning: 'always_triggered' in 'rules' detected 'Triage is running': 'always_true' was true

inspect.json

此 Codelab 包含一个带有“Inspect”(检查)数据的 inspect.json 文件, 但锻炼的效果是可预测的。此文件位于示例目录中的 snapshot/inspect.json

rules.triage

Triage 程序使用从一个或多个 .triage 文件加载的配置。 此 Codelab 使用位于示例目录中的 rules.triage 文件。

.triage 文件使用 JSON5,后者比 JSON 更易于读写:

  • 在最后一个列表项之后添加英文逗号是一种不错的样式。
  • 大多数密钥(包括所有有效的分类名称)不需要封装 引号。
  • /* 多行 */ 和 // 单行注释。

为“Inspect”(检查)值添加选择器

示例目录中的 inspect.json 文件指出了一些问题 与系统互动您将配置分类系统以检测 问题。

此步骤会将 Triage 配置为从 inspect.json 文件。

rules.triage 文件包含一个名为 select 的键值对部分。每个密钥 (name) 可在其他配置条目的正文中使用。每个值都是一个选择器 字符串。实际上,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。它还表示了 used_bytes 属性 该组件的检查树的 root 节点的 stats 子节点。

将上述选择器放入“select”部分。

生成选择器

手动输入选择器容易出错,因此可以使用 fx triage --select 输出有效的选择器。

fx triage --data snapshot --select total_bytes
INSPECT:bootstrap/fshost:root/data_stats/stats:total_bytes

可以使用多个 --select 参数。程序会生成所有 选择可能的选择器,选择快照的诊断数据,然后过滤 (grep) 所有 --select 参数。

添加计算

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”值告知输出 formatter 要求提供介于 0 到 1 之间的值,并以百分比形式显示该值。

试试看

以下命令将针对本地配置文件运行 Triage。

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?

测试规则

您可以(也应该!)为您的操作添加测试。对于每项测试,请指定值 以及这些值是否应触发您的规则

如需测试您添加的规则,请将以下内容添加到test rules.triage 文件:

test: {
    ....
    is_full: {
        yes: ["disk_full"],
        values: {
            disk_used: 98,
            disk_total: 100,
        }
    }
}

values 部分中的键应为 evalselect 的名称 条目。提供的值将覆盖条目要具有的值 选择或计算出来的值

您还可以测试不应触发操作的条件:

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",

再次运行分类。错误应该会消失,取而代之的是 事实上,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",
    }
}

annotations.json

快照包含一个文件 annotations.json,该文件包含有关以下各项的信息: 构建、开发板、正常运行时间等。

您可以使用函数 Annotation() 和 单个字符串参数,它是文件中 JSON 对象的键。对于 示例,

eval: {
    using_chromebook: "Annotation('build.board') == 'chromebook-x64'",
}

使用多个配置文件

您可以添加任意数量的 Triage 配置文件,甚至可以使用变量 在另一个文件中定义。这涉及很多应用:

  • 一个文件用于存储磁盘相关变量和操作,另一个文件用于 与网络相关的变量和操作。
  • 用于定义产品特定编号的文件。
  • 为特定工程师或团队单独创建文件。

添加“product.triage”文件包含以下内容:

{
    eval: {
        max_components: "4",
    },
}

请注意以下几点:

  • .triage 文件中可以省略空白部分。此文件不包含 selectacttest 条目。
  • 虽然 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 位整数或布尔值。
  • 算术表达式使用 + - * / // 运算符,具有普通的顺序和 操作的优先级。
  • 除法运算符 / 生成一个浮点值。
  • 除法运算符 // 生成一个整数值,将结果截断 接近 0,即使使用浮点参数也是如此。(请注意,这与 Python 3 不同, 其中 // 向下截断。)
  • + - * 会保留其操作数的类型(将混合提升为浮点数)。
  • 比较运算符为 > >= < <= == !=
  • 比较运算具有布尔值结果类型,可用于触发操作。
  • 您可以在一条 eval 规则中合并计算和比较项。
  • 您可以使用括号。
  • 您可以将 evalselect 条目的键名称用作变量。
  • 可以在所有地方使用空格,在除内部以外的所有地方都可以使用空格 filename::variable 命名空间型变量。

预定义函数

Triage 提供了可在 eval 表达式中使用的预定义函数:

  • Max(value1, value2, value3...) 返回最大值,类型为 置顶。
  • Min(value1, value2, value3...) 返回最小值,类型为 置顶。
  • And(value1, value2, value3...) 接受布尔值参数,并返回 值的逻辑与。
  • Or(value1, value2, value3...) 接受布尔值参数,并返回 值的逻辑或。
  • Not(value) 接受一个布尔值参数,并返回该参数的逻辑 NOT。
  • 如果存在以下情况,则 SyslogHas(matcher)KlogHas(matcher)BootlogHas(matcher) 会返回 true: 对应的日志文件都有一个行匹配匹配器,该匹配器是一个字符串 包含正则表达式。
  • Annotation(key) 会返回 annotations.json 中的对应值 文件。
  • Option(value1, value2, value3...) 会返回第一个有用的值, 支持选择器迁移和默认值:第一个非空列表, 非缺失值(如果有);或者为空列表;或缺失。
  • 如果值表示错误,Missing(value) 会返回 true。
  • Days()Hours()Minutes()Seconds()Millis()Micros()、 和 Nanos() 计算值以与单调时间戳进行比较。
  • Now() 会返回诊断数据发生时的大致时间戳 创建。
  • StringMatches(value, regex) 将指定的正则表达式应用于指定的 值,如果有匹配,则返回 true。正则表达式的语法是 支持。正则表达式 crate

函数式编程

分类可以将函数应用于值的矢量。向量的格式 "[expr, expr, expr...]"。一些选择器会返回多元素矢量。

Triage 提供 Map()Fold()Filter()Count() 函数, 处理矢量,使用 Fn() 为 Map、Fold 和 lambda 定义函数或 lambda 要应用的过滤器,以及 Apply() 将 Fn() 应用于参数。

如需了解详情,请参阅配置 fx 分类

延伸阅读

请参阅 fx triage 了解最新功能和选项 - 分类 不断改进!