blob: cf1b6fcfca3d9857a2bdd7225e095e5da34a5ea2 [file] [view]
# Configuring `fx triage`
[Triage](README.md) analyzes snapshots according to config files.
## Overview
Triage allows anyone to easily add new ways to analyze `fx snapshot` data for
off-nominal conditions.
By default, the config files are read from
`//src/diagnostics/config/triage/*.triage`. Just add a new config file there.
Config file syntax is JSON5.
Each config file specifies four kinds of configuration: Selectors and Evals
(collectively called "Metrics"), Actions, and Tests.
* Selectors load values for use by Evals and Actions.
* Evals calculate values for use by Evals and Actions.
* Actions determine how to act upon certain specified values.
* Tests include sample data to verify that specified Actions trigger
correctly.
Each Select, Eval, Test, and Action has a name. Thus, the structure of a config
file is:
```json5
{
"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": { .... }
}
}
```
## Names and namespaces
Select, Eval, Action, Test, and config file names consist of one
alphabetic-or-underscore character followed by zero or more
alphanumeric-or-underscore characters. Thus, "abc123" and "_abc_123" are valid
names, but "123abc", "a.b.c", and "abc-123" are not. In particular, file names
are not allowed to contain periods except for the `.triage` extension.
Evals, Tests, and Actions in one file can refer to Selectors, Evals, and Actions
in another file. The file basename is used as a namespace. `::` is used as the
separator. For example, if file `foo.triage` is loaded and contains a Metric
named `bar` then any config file may refer to `foo::bar`.
Names may be reused between Metrics, Tests, and Actions, but not between Select
and Eval.
NOTE: The current version of the program is not guaranteed to enforce these
restrictions.
### Selectors
Selectors use the Selector format. The text before the first `:` selects the
component name from the `inspect.json` file. The `.`-separated middle section
specifies Inspect Node names forming a path to the Property named after the
second `:`.
TODO(cphoenix) - Clarify this section once the correct selector-crate is in
place.
### Calculation
Eval strings are infix math expressions with normal operator precedence.
() may be used.
Arithmetic operators are + - * / //. / is float division; // is int division.
Functions are a function name, '(', comma-separated expression list, ')'.
Provided functions include:
* Boolean
* `And (1+ args)`
* `Or (1+ args)`
* `Not (1 arg)`
* `Missing(value)` returns true if the value is an error indication.
* Numeric
* `Min (1+ args)`
* `Max (1+ args)`
* Functional
* `Fn([name1, name2, ...], expression)`
* `Map(function, vector1, vector2, ...)`
* `Fold(function, vector, optional_start_value)`
* `Filter(function, vector)`
* `Apply(function, [arg1, arg2, ...])`
* `Count(vector)`
* Time
* `Days()`, `Hours()`, `Minutes()`, `Seconds()`, `Millis()`, `Micros()`,
and `Nanos()` calculate values for comparison with monotonic timestamps.
* `Now()` returns the approximate timestamp when the Diagnostic data was
created.
* Other
* `Option(value1, value2, value3...)` returns the first useful value, to
support selector migrations and defaults: the first non-empty-list,
non-Missing value if any; or empty list if one was given; or Missing.
* `Annotation(string)` fetches the corresponding key from
the annotations.json file, if present.
Metric type follows the type read from the Inspect file. Currently, UInt is
converted to Int upon reading. Operating on mixed Int and Float promotes the
result to Float.
Boolean operations are > < >= <= == !=. The equality tests == and != compare
numbers, Booleans, strings, and vectors. > < >= <= only compare numbers.
Whitespace is optional everywhere, but recommended around infix operators.
Metric names, including namespaced names, do not need to be specially delimited.
#### Functional programming and vectors
Every selector actually returns a vector, but one-item vectors are
automatically unwrapped for the purposes of arithmetic and boolean
calculations. Inspect selectors without wildcards return a one-item
vector unless the same moniker occurs multiple times in inspect.json.
Selectors with wildcards, selectors for `bootstrap/driver_manager` and
`netstack.cmx`, and (eventually) selectors on logs, may return
multiple items in a vector. To process such values, Triage provides the
following functions:
* Fn(parameters, expression) - for example, "Fn([a, b], a+b)"
* Map(function, vector1, vector2...)
* Fold(function, vector) or Fold(function, vector, start_value)
* Filter(function, vector)
* Count(vector)
Vectors of values are written `[ expr, expr, expr ]`.
If a `values` argument to Map is not a vector, its value is applied to each
iteration. If all `values` are not vectors, or no `values` are supplied, an
empty vector is returned. If the vector `values` are different lengths, the
shortest one determines the result length and remaining values are not used.
Count() does not check the type of items in a vector `values`. Count() of a
non-vector `values` returns Missing.
If a Fn expression is the entirety of an 'eval' expression, the name of that
expression can be used as the first argument to Map, Fold, or Filter.
If a function has the wrong arity for its arguments, the function it was passed
to returns Missing. If the function's evaluation fails, for example due to
inappropriate types, the function it was passed to may return a partial value:
* Map returns a vector, some elements of which may be Missing.
* Fold returns Missing.
* Filter expects its filter function to return Boolean true or false. If that
function returns anything else, including Missing, Filter adds a Missing
value at that point in its result list.
## Actions
Each Action determines how to surface information for a given selector.
Currently, there are two types of actions, "Warning" and "Gauge". Actions are
specified by providing the appropriate value for the `type` field.
### Warning Type
A `Warning` is an action that is used to raise an alert when a boolean condition
is met.
`Warning` supports the following fields:
* `trigger`, a required field, specifies the name of a Metric that supplies a
Boolean value.
* `print`, a required field, specifies a string to output when the warning is
raised.
* `tag`, an optional field, associates a tag with this Action.
* `file_bug`, an optional string field, specifies that a bug should be filed
and where. Triage does not file bugs directly; this field simply informs the
consumer (a human user or an automated pipeline). It can be a Monorail
component (e.g. "I18N>Fonts") or references to other issue trackers
understood by the consumer.
```json5
"actions": {
"disk_usage_high": {
"type": "Warning", "trigger": "disk_used / disk_total > 0.95", "print": "Disk usage is high!"
}
}
```
### Gauge Type
A `Gauge` is a snapshot of a particular value at the time Triage is invoked.
`Gauge` supports the following fields:
* `value`, a required field, specifies a value to display.
* `format`, an optional field, specifies formatting rules for the gauge's value.
#### Format
The `format` field allows users to control how the gauge value is displayed. If
this field isn't provided, or if an invalid value is given, then value will be
displayed as is. `format` supports the following values:
* `percentage`: prints a float as a percentage value.
```json5
"actions": {
"disk_usage": {
"type": "Gauge", "value": "disk_used / disk_total", "format": "percentage"
}
}
```
## Tests
Each Test specifies:
* Sample data, keyed by `inspect`
* A list of actions that should trigger given that data, keyed by `yes`
* A list of actions that should not trigger given that data, keyed by `no`
The sample data is in the same format as an inspect.json file: an array of maps
where each map contains `path` and `contents` fields.
```json5
"tests": {
"test1": {
"yes": ["action1", "action2"],
"no": ["action3"],
"inspect": [
{
"path": "global_data",
"contents": {"root": {"stats":
{"total_bytes": 10, "used_bytes": 9}}}
}
]
}
}
```