配置分类

分类功能会根据配置文件分析诊断数据。

概览

借助分类功能,任何人都可以轻松添加新方法来分析非正常条件下的 fx snapshot 数据。

默认情况下,系统会从 //src/diagnostics/config/triage/*.triage 读取配置文件。只需在该目录中添加一个新配置文件即可。

配置文件语法为 JSON5。

每个配置文件都指定了四种配置:选择器和评估(统称为“指标”)、操作和测试。

  • 选择器会加载值,以供评估和操作使用。
  • 评估会计算值,以供评估和操作使用。
  • 操作用于确定如何对特定指定值执行操作。
  • 测试包含示例数据,用于验证指定的 Action 是否正确触发。

每个选择、评估、测试和操作都有一个名称。因此,配置文件的结构如下:

{
    "select": {
        "select1": "type:component:node/path:property",
        "select2": "type:component:node/path:property"
    },
    "eval": {
        "name1": "select1+select2",
        "name2": "select1 - select2"
    },
    "act": {
        "action1": { .... },
        "action2": { .... }
    },
    "test": {
        "test1": { .... },
        "test2": { .... }
    }
}

名称和命名空间

Select、Eval、Action、Test 和配置文件名称由一个小写字母或下划线字符后跟零个或多个字母数字或下划线字符组成。因此,“abc123”和“_abc_123”是有效名称,但“123abc”“a.b.c”和“abc-123”无效。具体而言,文件名不得包含英文句点,但 .triage 扩展名除外。

一个文件中的评估、测试和操作可以引用另一个文件中的选择器、评估和操作。文件基本名称用作命名空间。:: 用作分隔符。例如,如果加载了文件 foo.triage 且其中包含名为 bar 的指标,则任何配置文件都可能引用 foo::bar

指标、测试和操作之间可以重复使用名称,但选择和评估之间不能重复使用名称。

用户定义的名称必须以小写字母开头。语言提供的函数以大写字母开头。

注意:当前版本的计划不保证会强制执行这些限制。

选择器

选择器使用 Selector 格式。第一个 : 之前的文本会从 inspect.json 文件中选择组件名称。用 . 分隔的中间部分指定了检查节点名称,这些名称构成了指向第二个 : 之后命名的媒体资源的路径。

计算

Eval 字符串是具有正常运算符优先级的算术中缀表达式。

可以使用 ()。

算术运算符包括 + - * / // /? //?/ 是浮点除法;// 是整数除法。使用 ? 的除法运算符在除以 0 时会返回 Problem::Ignore。

函数是函数名称,格式为“(”,“逗号分隔的表达式列表”,“)””。提供的函数包括:

  • 布尔值
    • And(1+ args)
    • Or(1+ args)
    • Not(1 arg)
    • 如果值是 Missing 类型错误指示,Missing(value) 会返回 true。
    • 如果值是任何类型的错误,Problem(value) 会返回 true。
    • True() 返回 true
    • False() 返回 false
  • 数字评分标准
    • Min(1+ args)
    • Max(1+ args)
    • Abs(1 arg)
  • 功能
    • Fn([name1, name2, ...], expression)
    • Map(function, vector1, vector2, ...)
    • Fold(function, vector, optional_start_value)
    • Filter(function, vector)
    • Apply(function, [arg1, arg2, ...])
    • CountProperties(vector) 用于统计矢量中的属性数量。
    • CountChildren(vector) 用于统计矢量中的子元素(节点)数量。
  • 时间
    • Days()Hours()Minutes()Seconds()Millis()Micros()Nanos() 会计算值,以便与单调时间戳进行比较。
    • Now() 会返回诊断数据的创建时间大致时间戳。
  • 其他
    • Option(value1, value2, value3...) 会返回第一个有用值,以支持选择器迁移和默认值:第一个非空列表、非缺失值(如果有);或空列表(如果已指定);或缺失。
    • Annotation(string) 会从 annotations.json 文件(如果有)提取相应的键。
    • 如果 syslog、内核日志或上次启动日志包含与正则表达式匹配的行,SyslogHas(regex)KlogHas(regex)BootlogHas(regex) 会返回 true
    • StringMatches(value, regex) 会将给定的正则表达式应用于给定值,如果存在匹配项,则返回 true。正则表达式语法是 Rust regex crate 支持的语法。

指标类型遵循从 Inspect 文件读取的类型。目前,UInt 会在读取时转换为 Int。对混合 Int 和浮点数进行运算会将结果提升为浮点数。

布尔运算符包括 > < >= <= == !=。等式测试 ==!= 会比较数字、布尔值、字符串和向量。> < >= <= 仅比较数字。

可以在任意位置使用空格,但建议在内嵌运算符周围使用空格。

指标名称(包括命名空间型名称)无需使用特殊分隔符。

函数式编程和矢量

每个选择器实际上都会返回一个矢量,但系统会自动展开单个元素的矢量,以便进行算术和布尔运算。不含通配符的检查选择器会返回一个包含一个元素的矢量,除非 inspect.json 中出现多次相同的标识名。

包含通配符的选择器、bootstrap/driver_managercore/network/netstack 的选择器,以及(最终)日志的选择器可能会在矢量中返回多个项。为了处理此类值,Triage 提供了以下函数:

  • Fn(parameters, expression),例如 Fn([a, b], a+b)
  • Map(function, vector1, vector2...)
  • Fold(function, vector) 或 Fold(function, vector, start_value)
  • Filter(function, vector)
  • Count(vector)

值矢量会写入 [ expr, expr, expr ]

如果 Map 的 values 参数不是矢量,则其值会应用于每个迭代。如果所有 values 都不是矢量,或者未提供任何 values,则返回一个空矢量。如果矢量 values 的长度不同,则最短的矢量决定了结果的长度,其余值将不被使用。

Count() 不会检查矢量 values 中的项类型。非矢量 values 的 Count() 会返回“Missing”。

如果 Fn 表达式是“eval”表达式的全部内容,则该表达式的名称可用作 Map、Fold 或 Filter 函数的第一个参数。

如果函数的参数个数不正确,则传递给它的函数会返回“Missing”。如果函数的求值失败(例如,由于类型不当),传递给它的函数可能会返回部分值:

  • Map 会返回一个矢量,其中可能缺少一些元素。
  • 缺少折叠返回。
  • Filter 预期其过滤函数会返回布尔值 true 或 false。如果该函数返回任何其他值(包括“缺失”),过滤器会在其结果列表中相应位置添加“缺失”值。

操作

每项操作都会决定如何显示给定选择器的信息。目前,操作分为两种类型:“警告”和“仪表板”。您可以通过为 type 字段提供适当的值来指定操作。

警告类型

Warning 是一种操作,用于在满足布尔值条件时发出提醒。

Warning 支持以下字段:

  • trigger(必填)用于指定提供布尔值的指标的名称。
  • print(必需字段)用于指定在发出警告时输出的字符串。
  • tag(可选字段)用于将代码与此 Action 相关联。
  • file_bug 是一个可选的字符串字段,用于指定应提交 bug 以及提交到何处。分类不会直接提交 bug;此字段只是告知使用方(人工用户或自动化流水线)。它可以是问题跟踪器组件(例如“Fuchsia > 国际化 (i18n)”),也可以是引用了使用方理解的其他问题跟踪器。
    "actions": {
        "disk_usage_high": {
            "type": "Warning", "trigger": "disk_used / disk_total > 0.95", "print": "Disk usage is high!"
        }
    }

仪表类型

Gauge 是调用分类功能时特定值的快照。Gauge 支持以下字段:

  • value(必填字段)用于指定要显示的值。
  • format(可选字段)用于指定仪表板值的格式设置规则。

格式

借助 format 字段,用户可以控制仪表板值的显示方式。如果未提供此字段,或者提供的值无效,则值将按原样显示。format 支持以下值:

  • percentage:将浮点值以百分比值输出。
    "actions": {
        "disk_usage": {
            "type": "Gauge", "value": "disk_used / disk_total", "format": "percentage"
        }
    }

测试

每项测试都指定以下内容:

  • inspect 键值对排列的示例数据
  • 应在有此数据时触发的操作列表,按 yes 键值对
  • 在给定数据的情况下不应触发的操作的列表,按 no 键值对排序

示例数据的格式与 inspect.json 文件相同:一个映射数组,其中每个映射都包含 pathcontents 字段。

    "tests": {
        "test1": {
            "yes": ["action1", "action2"],
            "no": ["action3"],
            "inspect": [
                {
                    "path": "global_data",
                    "contents": {"root": {"stats":
                        {"total_bytes": 10, "used_bytes": 9}}}
                }
            ]
        }
    }