fleetlessfleetlessdocs
Reference/fleetless.yaml/Alerts

🚨 Alerts

An alert is a state machine, ok and firing, nested under the datapoint it watches. Nesting is what makes an orphaned alert unrepresentable.

yaml
datapoints:
  battery_soc:
    topic: /battery
    type: sensor_msgs/msg/BatteryState
    field: percentage

    alerts:
      low_battery:
        name: Battery low
        severity: warning
        enabled: true
        condition: { fire_at: 15, resolve_at: 18 }
field type bounds absent means
condition.fire_at number, text or boolean a number must be finite required
condition.resolve_at number finite, must differ from fire_at, allowed only when fire_at is a number the condition is an equality
name text 1 to 120 characters the bare key is shown instead
severity warning or error — warning
enabled boolean — true

The key is the identity, and name is not. A label can be reworded freely. Renaming an alert is a delete plus a create: runtime state is lost, and an alert that is still true fires again on the next sample.

The condition has no discriminator

Whether the condition is an upper threshold, a lower one or an equality follows from the two values in it.

written means
{ fire_at: 80, resolve_at: 75 } fires at 80, ok at 75 — an upper threshold
{ fire_at: 15, resolve_at: 18 } fires below 15, ok at 18 — a lower threshold
{ fire_at: true } fires while the value is true
{ fire_at: 3 } fires while the value is exactly 3

Without resolve_at it is an equality. It fires while the value equals fire_at and is ok as soon as it differs, which is the only form a boolean or a string condition can take.

With resolve_at it is a threshold, and the gap between the two is the hysteresis. That gap is mandatory: without it a value sitting on the line oscillates and emits an event on every crossing. A resolve_at equal to fire_at is refused, and so is a resolve_at on a non-numeric fire_at — a boolean has two values and text has no ordering to take a direction from.

An equality works on any field, including a Bool or a mode string. Only a threshold needs a numeric field, because only a threshold compares magnitudes; one on a text field is refused as requires_numeric_field.

severity changes nothing but the colour

Nothing is escalated, retried or delivered differently. The same event is written, at the same moment, to the same places, and the severity travels with it and colours the alert wherever it is shown.

A resolved alert is the exception worth knowing: its event is always info, whatever the alert’s own severity. Resolving is good news regardless of how bad the firing was.

enabled defaults the other way from retention

An alert that is written down watches unless it is explicitly switched off. That is how one is silenced without losing the key that identifies it, and it is the opposite of retention.enabled, which is off until you ask for it.

Where an alert goes

Every transition writes an org event, which reaches the robot overview, the organisation overview and the activity log. The event carries the alert’s name, the value that crossed and the threshold or expected value it crossed.

No mail is sent. Webhooks will come later and will be how an alert reaches another system.

Runtime state across a publish

Alerts are evaluated in the cloud. They become active on publish and never have an effect on the robot. What happens to a running state depends on what the publish changed.

case runtime state
the condition is unchanged kept, with the time it entered that state
the condition changed reset to ok, the last value discarded
a new alert starts ok
the key is gone the alert is deleted, and its state with it

Only the condition resets the state. name, severity and enabled deliberately do not: an alert re-enabled mid-firing should still read firing.

Alerts are one of the three groups a datapoint without a field may not carry. The other two, and the rest of the datapoint, are on Datapoints; what a publish does and does not send to the robot is on the overview.