Back to Home

Routing Rule configuration

A Routing Rule decides which incoming alerts are sent to which Schedule. It references a Schedule, so create the Schedule first.

Fields

FieldTypeRequiredDefaultNotes
namestringYesRule name. Cannot be empty.
schedule_idnumberYesThe target Schedule. Must reference an existing Schedule (greater than 0).
match_modestringYesallall (every condition must match) or any (at least one). An empty value defaults to all.
prioritynumberYes0Lower values are evaluated first. Zero is allowed.
descriptionstringNo""Free-text description.
conditionsarrayNo[]List of { field, op, value } conditions to match against the alert. op is one of equals, not_equals, contains, matches, exists. See What conditions match against.
is_activebooleanNotrueWhether the rule is active. Can only be set when updating an existing rule, not at creation.

What conditions match against

Conditions are evaluated after the Webhook's Transformation Rule has run, against the alert as Unit Oncall will store it. A field can be either:

  • A normalized alert fieldfingerprint, title, message, severity, timestamp, labels, tags. These hold the transformed value.
  • source — always read straight from the incoming payload's source field. A Transformation Rule cannot map source, so a source entry in mappings has no effect and a source condition always sees what your monitoring tool sent.
  • A path into the incoming payload — dot-separated, for example custom_fields.region. These hold the value exactly as your monitoring tool sent it.

If the Webhook binds a Transformation Rule, write conditions against the transformed value. A rule that maps P1 to critical means the alert's severity is critical by the time routing runs, so severity equals critical matches and severity equals P1 does not. Writing the pre-transformation value is easy to miss because severity exists still matches either way — the rule simply never fires and every alert falls through to the Webhook's default_schedule_id.

Normalized fields always reflect the alert, including when they end up empty. For example, if tags arrives as a delimited string rather than an array and no Transformation Rule reshapes it, the alert carries no tags and a tags condition sees no tags. Use the Transformation Rule's array_delimiter option to split such a value into an array.

The exists operator asks whether the alert has that field at all, so a normalized field the alert never received — say labels on a payload that sends none — does not match exists.

The matches operator takes a regular expression, and its pattern is limited to 512 characters. The limit counts characters rather than bytes, so a pattern written in Japanese or any other non-ASCII script gets the same 512. A longer pattern — or one that is not a valid regular expression — is rejected when you save the rule, not silently ignored at routing time.

A second limit caps how large the pattern becomes once compiled: 2,000 instructions. Character count alone does not bound this, because a bounded repetition such as {100} expands into roughly that many instructions — (?:a{100}){10} is only 14 characters but compiles to about 1,000. Ordinary patterns are nowhere near the limit: a 512-character literal is about 514 instructions, and the conditions people actually write are usually under 50. You will only run into it by nesting large {n} repetitions, and the fix is to write the repetition more loosely (for example a+ or a{1,100} instead of stacking fixed counts).

Some tools send a normalized field name as an object — Prometheus and Alertmanager send labels that way. As long as no Transformation Rule produces a value for that field, the object is left untouched and dot paths into it (labels.env) keep working. Once a Transformation Rule does produce a value for the field, that value replaces the object and those dot paths stop resolving — match on the transformed field itself instead.