Automation Triggers - rogers-group-inc/polaris GitHub Wiki
Step 3 of the wizard. What the automation watches, at what severity.
| Kind | Watches | Scoped to devices? |
|---|---|---|
| Asset metric | a number a device reports | yes |
| Asset state | a field on the Asset row, or a per-dimension state | yes |
| Path Monitor | a path check's results, or its route changing | agent hosts only, plus the Polaris server if ticked |
| Host metric | the Polaris server's own health | no |
| Event | an audit Event arriving | yes |
| Change | a tracked field changing | yes |
| Composite | a tree of the above | yes (device-kind) |
In the wizard the Trigger type dropdown groups these: Device conditions (asset metric, asset state, and trees of them), Path Monitor, Polaris host conditions, Audit event match and Change detection.
A number, compared against a threshold.
| Metric | Unit | Dimension |
|---|---|---|
cpuPct โ CPU utilization |
% | โ |
cpuCorePct โ CPU core utilization
|
% | โ (one alert per device, naming the hot cores โ see below) |
memPct โ Memory utilization |
% | โ |
memUsedBytes โ Memory used |
bytes | โ |
sessionCount โ Active sessions |
โ | โ |
responseTimeMs โ Response time |
ms | โ |
uptimeSec โ Uptime |
sec | โ |
probeLossPct โ Packet loss (probe) |
% | โ (windowed ratio โ see below) |
hwSensorValue โ Hardware sensor value |
sensor's own | sensor class, sensor name |
hwSensorAlarm โ Hardware sensor alarm
|
0/1 | sensor class, sensor name |
storageUsedPct / storageUsedBytes โ Storage used
|
% / KB, MB, GB, TB | mount path (one condition in the builder โ see below) |
storageDaysUntilFull |
days | mount path |
ifInErrorRate / ifOutErrorRate
|
errors/s | interface name |
ifInBps / ifOutBps
|
bps | interface name |
sdwanLatencyMs / sdwanJitterMs / sdwanPacketLoss
|
ms / ms / % | health check, member |
ipsecThroughputBps |
bps | tunnel name |
customWidgetValue |
โ | widget |
customStateValue โ Device state flag |
0/1 | state probe, row |
The path check metrics are not here โ they have their own trigger type, Path Monitor.
Storage used is one condition in the builder, with a unit select beside
the value: % of the filesystem, or an amount used in KB, MB,
GB or TB (1024-based, the same figures the asset's storage table
shows). Percent is stored as storageUsedPct; a size is stored as
storageUsedBytes in bytes, and reads back in the largest unit that keeps the
value at 1 or more. Severity levels share the condition's choice between
percent and size, but each can state its size in its own unit. The clear
threshold on the reset step is in the fire threshold's unit.
Changing a condition to a metric measured in a different unit (percent to days, percent to a size) empties the severity levels' values and the clear threshold, because a number written for one unit means nothing in the other. Switching between metrics in the same unit keeps them.
A metric automation can act on the device as well as tell people about it: Memory utilization above 90 % for 15 minutes with a reboot action books a reboot of the device for the night.
Alerts on path checks: whether a URL or service answers, how fast, and the route traffic takes to it. Pick Path Monitor as the trigger type, then choose what fires it:
-
A path check result meets the conditions below. The condition dropdown lists the path conditions and nothing else:
Condition Unit Notes pathOkโ Path check resultReachable / Unreachable the default: Unreachable pathLatencyMsโ Path latencyms a failed run has no latency โ that is pathOk's to reportpathFailurePctโ Path failure rate% windowed ratio, like packet loss, but no ceiling โ 100% failing is the alert pathHttpStatusโ Path HTTP statusโ pathHopCountโ Traceroute hop counthops from the traceroutes, not every run pathTlsDaysLeftโ TLS certificate days remainingdays HTTPS checks only Pick the check on the condition row; blank means every check, one alert each.
-
A check's route changes (traceroute). Fires each time a source's traceroute takes a different set of hops (at most once per 10 minutes per source and check).
Which sources it watches. Only devices with an active Polaris Agent โ the Devices step's conditions narrow those, and its preview counts only agent hosts once the automation is a Path Monitor one. The Trigger step shows the pool it will watch.
Include the Polaris server's own runs adds the server as a source when a check runs from the Polaris server. A new Path Monitor automation has it ticked. Its alerts say Polaris server where a device name would be, and:
- the Devices-step filter, maintenance windows and dependency suppression do not apply to it โ it is not a device;
- with more than one condition, only agent hosts are evaluated;
- it cannot be combined with a custom reset condition (the wizard refuses the save) โ reset automatically instead.
The device a path alert is about is the host that ran the check, not the target. Path results never change that host's Up / Down status. A tree can't mix path conditions with device conditions โ make them separate automations.
cpuCorePct finds a single-threaded application: one thread pinning one
core of a 16-core server reads about 6% as CPU utilization, so the
all-cores condition never sees it.
The hold is counted per core. "Above 90% sustained for 3 polls" means the same core was above 90% on three polls in a row. Different cores each going over 90% once, which is how ordinary multi-threaded load looks, does not fire. Set the number of polls in Sustained for, as for any other condition.
-
One alert per device. It names the cores that stayed over the line for
the whole hold, busiest first, for example
Core 3 (97%). With the In-app Alert template left blank, the message reads<automation>: <device> [Core 3 (97%)] (threshold 90). In your own template,{dimension}prints the same core list. The email shows them in a CPU cores row, with the top 5 processes by CPU and the CPU and memory charts. - It clears when every core is back under the line for the reset's clear-sustain count, not just the core that fired.
- Only hosts that report per-core figures: the Polaris Agent, vCenter (VMs and ESXi hosts) and Unraid / TrueNAS hosts. SNMP, FortiOS, WinRM, SSH and Proxmox VE do not report cores, so those devices never fire this condition.
-
The regular CPU alert wins. While a device has an open CPU
utilization (
cpuPct) alert from any automation, a per-core automation stays quiet on that device. If it had already alerted, its alert clears as superseded, because when every core is busy the device-wide alert already says so. Acknowledging the CPU alert does not change this; clearing it does. This does not apply to a per-core condition inside a multi-condition automation. See rule 89.
hwSensorAlarm reads the per-sensor alarm bit the collectors already gather,
rather than a threshold you invent. Prefer it โ the device knows its own
per-model limits, and for a fan tray or a PSU the health is in that bit rather
than in any comparable number. See rule 24.
A source that publishes no alarm bit is excluded, never read as 0. An
unrecognised non-empty status maps to alarm; ENTITY-SENSOR-MIB's unavailable(2)
maps to null โ an empty SFP cage is not a fault.
probeLossPct is a windowed ratio, not an aggregation. Its field is
relabelled History (minutes) โ mandatory, default 15, range 5โ1440 โ and
that window is the reading. A separate optional Sustained for (polls) field
carries a hold on top of it โ the window in minutes, the hold in readings, each
stating the unit it is actually stored in.
Three things it does that no other metric does (rule 29):
- It counts packets, not rows, wherever it can. An ICMP sweep row describes a whole burst and carries packets sent / received, so an asset with burst rows in the window is measured from those sums. Otherwise it falls back to the row ratio.
-
Only an answering device reports loss. The resolver admits
upandwarningonly. A dark passive device would otherwise sit at 100 % with no asset-down alert to supersede it. -
A reading at or above the rule's
ignoreAtOrAboveceiling is not a reading โ default 100, so only a total outage is suppressed. Polaris opts its own baseline rule out at 90. Lower it if you do not want an alert trailing every outage. This box is offered for packet loss only โ a path check's failure rate has no ceiling, because 100 % there means every run to the target failed, which is the alert.
And the failures of an outage are excluded from the metric: every maximal
run of consecutive failures that reached down is dropped whole, onset
included. Without that, a switch dark for twelve minutes comes back, starts
answering, and its 30-minute window still reads 40 % โ so a "High packet loss"
warning lands minutes after the recovery about the outage that already paged
someone.
The chart can legitimately disagree with the alert. The loss chart counts every probe in its window, outage failures included, because a picture of the window has to be continuous โ a gap renders as a flat 0 % line, which reads as "no loss" when the truth was "totally dark". So a caption can read avg 40 % under an alert that fired at 8 %. They answer different questions, and only the caption's is reconstructible from the picture.
When a device goes down, any alert already open about something that device reports (CPU, memory, an interface, a sensor, an SD-WAN SLA or member, an IPsec tunnel, FortiLink) clears as superseded, and the asset-down alert speaks for the outage (rule 29). It sends no "resolved" message and runs no reset actions, because the condition has not recovered. Nothing new fires about the device while it is down. If the condition is still bad when the device comes back, it fires again as a fresh alert once its hold is met.
Without this, an alert open when the device goes dark would freeze, because no readings arrive to recover it. It would sit beside the asset-down alert for the whole outage and mail "resolved" the moment the device returned.
This does not apply to:
- the asset-down alert itself (
monitorStatus,consecutiveFailures) โ the stream-failing fields (telemetryFailingMinutes,systemInfoFailingMinutes) are not part of it, so they are handed off like CPU; - facts about the device that an outage does not change (
status,quarantined,firmwareVsPrimary,tag,dependencySuppressed); - path checks, which are measured from the device rather than about it;
- a multiple-condition automation with any of those in its tree;
- a device that is
passive,unknownorrecovering. Only a confirmeddownhas an asset-down alert to hand to.
For customStateValue and hwSensorAlarm the builder swaps the numeric
controls out: the threshold box becomes a select of the probe's own two labels
("Alarm" / "OK"), the comparator narrows to is / is not, and the aggregation
narrows to current state / at any point in / throughout. Severity bands
and hysteresis are hidden and server-rejected โ a ladder over two values means
nothing.
A field rather than a number.
Device-wide fields: monitorStatus ยท status ยท consecutiveFailures ยท
dependencySuppressed ยท quarantined ยท fortilinkStatus ยท firmwareVsPrimary ยท
telemetryFailingMinutes ยท systemInfoFailingMinutes ยท tag.
tag is Asset tag: pick a tag from the list (every tag on a device plus every
tag in the registry, so you can build a rule for a tag no device carries yet) and
choose is or is not. On the Devices step the same tag box suggests
category:name entries such as priority:Critical and region:<name>; the rule
stores the tag name itself (Critical; a region keeps its region: prefix) and
you can still type any name. Is is true
of a device carrying that tag, is not of one that does not. The match is the
whole tag, ignoring case. It is a fact about the device, so it keeps reading
while the device is down. Combine it with another condition to limit a rule to,
say, devices tagged prod; to limit which devices an automation covers at
all, use a tag condition on the Devices step instead.
Per-dimension fields: ifOperStatus ยท ifAdminStatus ยท ifIpAddress ยท
poeStatus ยท ipsecStatus ยท sdwanRuleStatus ยท sdwanSelectedMember ยท
sdwanMemberState (whether one WAN member of one health check is alive, as the
FortiGate judges it โ see SD-WAN).
This is the trigger that defines what down means. It carries a
missedPolls count, and that count is the definition of down for every device
it covers (rule 36).
-
You type it in the trigger step's
Sustained for (polls)field, below the condition tree โ the same field every other trigger states its hold in, doing its third job (see the table below). The caption under it turns the count into the wall-clock time to Down at the cadence your matched devices actually use, which is longer than count ร interval because a missed poll also costs its timeout. - Precedence resolves it โ same-rank ties go to the smaller count, then older, then lower id.
-
A device no such automation covers reads
passiveand is never judged. - The same automation owns the way back up: its reset hold, collected in
polls, holds the device in
recoveringuntil that many probes have answered. - It also decides what colour Down is on every chart and in every alert email โ the automation's own severity.
- Dependency-Down Bypass โ a checkbox row on the Actions step, under the In-app Alert card beside Require Acknowledgement โ lets this automation keep alerting about a device that is Dep. Down behind a down switch or firewall, the one opt-out from the silence every other automation observes (rule 78). The alert fires the moment the device turns Dep. Down, says DEPENDENCY DOWN, and names the upstream device that is actually down. One notification only: reminders and escalation wait until the upstream is back. See Dependency suppression.
See Monitor states for the whole machine.
What the parent FortiGate says about its FortiLink session to a managed
FortiSwitch, or its CAPWAP tunnel to a managed FortiAP: up / down /
unknown, and null on anything not FortiGate-managed.
It is deliberately a separate field from monitorStatus, and the
disagreement is the point: a switch reading monitorStatus = up with
fortilinkStatus = down is answering ICMP while its FortiLink session to the
gate is dead โ a fault the monitor loop cannot see, because it is asking the
switch.
Three refusals (rule 59):
- An unreadable controller writes nothing โ not
down, not even a refreshed timestamp. An expired token must not report a fleet-wide link outage. - Answered-but-absent is
unknown, neverdownโ a post-config-push window looks identical. - It never touches
monitorStatusor the failure counter.
unknown is offered in the picker deliberately: it is the reading for a device
the controller answered about but did not list, which on a FortiSwitch usually
means it has been unplugged long enough to age out of the managed-switch table.
An operator who wants "tell me when the gate stops seeing this switch at all"
writes != up, not == down.
A null produces no reading at all โ not a reading of null, which would make
!= up true of every workstation in a fleet-wide scope.
How a switch, access point or FortiGate's running firmware stands against the primary
image the Repository holds for its platform:
current, older or newer (rule 87). Polaris makes
the comparison from the parsed versions, so those three words are the only
readings โ the picker is closed.
The usual rule is != current, and the baseline automation Firmware differs
from repository primary (informational, switches and access points) is
exactly that. FortiGates have readings too, but the baseline's scope does not
include them โ add Firewall to its scope, or
write a rule of your own, to be told about gates. It is a to-do list, not a fault: the alert clears on its own once
the device is upgraded, or once a different image is made primary. == newer
names the fleet that is ahead of the image someone selected โ useful the day
an older image is made primary on purpose.
A device the Repository cannot place produces no reading at all: not a
switch, access point or firewall, no usable serial number (the platform is its first six
characters), no version Polaris can parse, or no primary image for its
platform. So a fleet-wide != current is true only of devices that really
differ, never of every printer and VM the Repository knows nothing about.
The reading is refreshed by the system-info pass and by discovery, which are
what update a device's firmware version โ a Sustained for (polls) hold counts
those, not the 60-second probe.
CPU & memory polls failing (minutes) and Interface polls failing
(minutes) read how long that stream's polls have been failing, in whole
minutes, counted from the first failed poll to the latest one
(rule 118). A stream that is working reads 0.
The usual rule is CPU & memory polls failing (minutes) โฅ 60: tell me when a
device's CPU and memory have not been collected for an hour. These fields are
separate from response time, and that is their point. A FortiGate that answers
ping or SNMP while its REST pull is refused reads monitorStatus = up, so the
down-detection automation never sees it. This one does.
-
No double alert for an outage. If the device goes down, an open alert
on either field is handed to the asset-down alert, like CPU or an interface
(see A device that goes down takes its other alerts with
it). Adding
monitorStatus == upto the same automation is still allowed if you want it written down. - The reading stops advancing when polling stops. It measures to the latest poll, not to the current time, so a device whose heavy streams are paused (missed probes, a down parent) does not climb toward the threshold.
- No reading for a stream that is never polled โ no collector for its method, or the stream switched off โ so a fleet-wide condition does not fire on devices that have no CPU or interface stream at all.
-
A
Sustained for (polls)hold counts that stream's polls (its own cadence), not the 60-second probe. - The alert email for the CPU & memory field draws the CPU chart, where the samples stop.
The port's current L3 address, compared as a string. Its reason for existing is
the negative form: != 0.0.0.0 is how you say "this interface actually has
an address".
That is the gate a rule about something riding that interface needs. An SD-WAN overlay's health check reports total packet loss whenever its underlay WAN port is unaddressed โ and that is the underlay's outage to alert about, not the overlay's.
The interface is integral here: the comparison is about one port, so the interface picker renders on the condition row itself rather than as a group filter.
The status of an IPsec tunnel, as the FortiGate reports it. Only tunnels you have pinned โ on the device's System tab or in bulk from Mass Pinning โ are ever read, so an unpinned tunnel can never raise an alert however the rule is written (rule 57).
The IPsec tunnel picker sits on the condition row and offers the tunnel names the devices you selected on the Devices step actually report โ a phase-1 name is not something to type from memory, and one that matches nothing saves cleanly and then never fires. Leave it blank and the condition covers every pinned tunnel on those devices, raising one alert per tunnel; fill it in and the condition is about that tunnel alone.
If the picker says the selected devices report no monitored IPsec tunnels, the tunnels have not been pinned yet โ pin them, then re-open the step.
The Polaris server's own health: cpuPct, memUsedPct, memUsedBytes,
loadAvg1/5/15, procRssBytes.
Unscoped โ the Devices step is discarded, because this is not about your devices.
Fires when a matching audit Event is written. Flat fields: an action pattern, a
minimum level (info / warning / error), a resource type.
Under those fields is a list of detail conditions โ a field inside the
event's own details and the value it has to read. Every condition must hold, and
each is compared as text, so direction is escalated matches the string the
event carries.
This is how an automation is made directional. capacity.severity_changed
is written both when capacity gets worse and when it partly recovers; the
built-in Capacity severity escalated rule carries direction = escalated so
it alerts on the way up and stays quiet on the way back down. Platform
end-of-life warning carries the same condition. Open either rule's trigger
step to see the row, change it, or take it off.
When the action pattern matches a capacity event (capacity.severity_changed,
capacity.severity_recovered, or a pattern such as capacity.*), the trigger
step also shows Alert after a capacity change holds for. Capacity is checked
every 10 minutes, and a severity change becomes an event only after every check
for this long agrees, so a short spike never alerts. Below it, the step shows
what was last recorded, or the change currently being waited out.
This is one setting for the whole install, not part of the automation. It decides when the event is written at all, so every capacity automation and the Events log see the same held event. It saves as soon as you change it, whether or not you save the automation. See rule 105.
To find the field names an action offers, open Events, click the event you want to alert on and read its details โ those keys are what a condition can name.
An event automation is device-scoped, and the filter filters the event's subject (rule 46). Two refusals follow from "the subject is a device":
- An event naming no asset โ an integration, a user, a login, the host itself โ cannot satisfy a device filter, so a filtered automation never fires on one. An unconstrained one still does, which is how the twelve seeded event automations keep working.
- Neither does an event whose asset row is already gone (
asset.deleted).
"Unconstrained" is asked first and separately: {allAssets: true}, a bare {},
or a condition tree with no rules. That distinction is load-bearing โ a stored
{} on an event automation means "any device", while a builder-authored empty
scope selects nothing.
Sugar over the change Events Polaris emits:
| Change type | Means |
|---|---|
lldp_neighbor_added / _removed
|
LLDP neighbour appeared / disappeared |
process_started / process_stopped
|
|
sdwan_failover |
SD-WAN member changed |
mclag_peer_lost |
|
wireless_station_connected |
|
firmware_changed |
firmware / OS version changed |
switch_port_changed |
|
wireless_ap_changed |
a roam |
gateway_firewall_changed |
the gate in front of the device changed |
fortilink_changed |
controller link changed |
A path check's route changing is under Path Monitor.
The Devices step's Polaris Agent installed field (yes / no) selects hosts with an active Polaris Agent. A Path Monitor automation applies it for you.
An AND/OR tree over several conditions, up to 3 deep and 10 leaves. One leaf saves as a plain single trigger; two or more save as a per-asset composite.
This is what lets one automation mix device-specific branches โ "interface wan1 down on CORE-SW OR storage /backup full on BACKUP-01" โ using device filter rows (below).
The step has a single duration field, and what it means depends on the condition above it. It renames itself โ and changes its unit โ to say which:
| Condition | The field | It means |
|---|---|---|
avg / median / min / max
|
Measured over / Poll Group Size, with a minutes | polls picker |
the measurement window โ a span of time, or a group of polls; see Poll groups below, which is the choice that picker offers |
probeLossPct |
History (minutes) | the window the ratio is measured across (see above) |
latest |
Sustained for (polls) | the sustain clock โ how many consecutive readings the condition must stay true for |
monitor status is down, as the automation's only condition |
Sustained for (polls), required | the missed-poll count โ how many polls in a row the device must miss before Polaris calls it down, which is also when this alert fires (rule 36) |
The last row is the one field that is not merely a clock on a reading: it is the reading's definition. So there is no hold stacked on top of it โ a hold would wait out a state the count itself just declared, and your number would quietly mean twice what it says. Add a second condition and the field goes back to being an ordinary sustain clock, because a count can only carry authority on an automation whose sole condition is that verdict.
The two units are not a cosmetic difference, and which one you get is not a
preference โ it is what the rule actually stores. A window is saved as
windowSec and the engine reads it as wall-clock time, so stating it in polls
would mean multiplying by whatever cadence the wizard had observed and presenting
the result as though you had said it; a hold is saved as forPolls and the engine
genuinely counts readings. Each field states the half that is true, and its
caption names the other half โ the poll estimate under a window, the wall clock
under a hold. Switching a condition's aggregation re-denominates the number
in the box rather than reinterpreting it: 10 minutes on a fleet polled every two
minutes becomes 5 polls, never a bare 10 that would quietly double the hold.
That ambiguity is real, so the step renders the trigger twice: once as an English sentence, and once as a formula directly underneath. The formula puts a measurement window inside the term and a hold clock outside it:
median(Hardware sensor[class="temperature"], 15m) >= 65 ยฐC
latest(CPU usage) > 90 % held 10m โ warning
The field is mandatory exactly when an aggregation is chosen, marked with a red asterisk, and refused at save rather than silently measured over the engine's default lookback.
One honest caveat the formula states rather than hides: the engine fetches
max(window, 15 min)of samples and reduces every row it fetched, so a window under 15 minutes is really measured over 15. The formula prints the configured window and says so.
A trigger states forPolls and a reset states
reset.sustainPolls, and the engine counts consecutive qualifying readings
(rule 19). A seconds value is kept as the
wall-clock mirror โ what the prose reads, and what sizes the sample window.
This matters because the engine ticks every 60 seconds while a device may be polled every five minutes. Counting ticks would charge five polls against one. The wizard asks the server for the actual cadence of the draft's own devices so it can convert, and says which cadence it converted at.
The same is not true of a measurement window, so the two are not stated in the
same unit. A window is windowSec โ the engine takes every sample whose
timestamp falls inside it and reduces them. It does not count to N. A window
typed as "60 polls" would really be 60 ร the cadence the wizard happened to
observe, and would stop describing the rule the moment that cadence changed โ a
window authored against a 60s poll stays an hour after the fleet moves to 300s.
The number of readings a window holds is a consequence of the window and the fleet's cadence, so it belongs in the caption, where it updates as the cadence does. Two consequences worth knowing when you read a window back:
-
A time window's denominator floats with availability. Missed polls write no
value, so an hour of
avgover a device dropping three quarters of its packets is the average of the quarter that answered โ not of 60 slots with holes in them. Poll groups (below) are the fix for that; if you want the misses themselves to alarm, that is whatprobeLossPctand down detection are for. -
A stored window that isn't a whole number of minutes is left alone until
you edit the field. A 90-second window shows
2and stays 90 across a save that never touched it; type2and it becomes 120, because typing it is stating it.
Switch the picker from minutes to polls and the field becomes Poll Group Size. Polls are then taken in groups of that many, and each group is aggregated into one reading.
This is the answer to the floating denominator above. Every group is the same size, so a lossy device is measured over the same number of samples as a healthy one โ what stretches is the wall-clock time a group takes to fill, not the number of measurements in it. The reading means the same thing at 0 % loss and at 40 %: when this device answers, this is how long it takes.
Choosing polls also reveals Sustained for (poll groups), which a minutes window does not get: how many consecutive groups must come out over the threshold before the alert fires. The two compose into "the last three groups of ten polls each averaged over 500 ms".
The groups do not overlap, and that is the point of them. Group 1 is polls 1โ10, group 2 is polls 11โ20, group 3 is polls 21โ30 โ three separate looks at the device, so three of them agreeing is real corroboration. It also makes the timing something you can work out in your head:
Time to alert = Poll Group Size ร Sustained for. A group size of 10 at a 60-second cadence takes 10 minutes to produce its first reading. Sustained for 3 means the alert arrives after 30 minutes โ assuming all three group averages were over the threshold.
| Minutes window | Poll groups | |
|---|---|---|
| Window | last 60 minutes | groups of 10 polls |
| Sample size | whatever landed โ floats with availability | fixed at the group size |
| A miss | shrinks the denominator | (response time: counts as the timeout โ see below) |
| Hold on top | none โ the window is the period | Sustained for, in groups |
| Before a full group | averages what it has | no reading at all โ it abstains |
| Time to alert | the window, once | size ร sustained |
Two behaviours worth knowing before you rely on it:
- A group has to fill before it reads anything. Nothing fires during the first group, however bad the device looks inside it โ that is the smoothing you asked for. Set the group size to the smallest number that hides the noise you don't care about, not the largest you can imagine.
-
On a lossy device everything takes proportionally longer, because a group
waits for measurements rather than for the clock. That is deliberate: fewer
measurements means less certainty, so more evidence before paging. A device bad
enough that groups never fill has a packet-loss problem rather than a latency
one, and
probeLossPctis the metric that says so.
The practical reason to reach for it: poll groups will not page you for a single spike. One 1500 ms response inside an otherwise healthy group of ten never pulls that group's average over 500, so the run never starts โ while a device that has genuinely slowed clears the line in group after group and fires on schedule.
Response time defaults to a poll group size of 10, and it behaves differently from every other metric inside that window โ because it is the only metric whose failure has a duration attached. A missed CPU reading is an absence; there is no number to put there. A missed response-time poll waited the device's full probe timeout and heard nothing, which is a fact about the device measured in the same unit as the metric.
So, inside a response-time poll group:
- A missed poll counts as the probe timeout configured for that device. Not skipped, not zero. Skipping it would let a device answering one poll in ten read exactly as fast as one answering every poll; zero would make the worst device on the network look like the best.
- Going Down resets the window. Everything up to and including the poll that declared the outage is discarded. Without this, an outage's timeouts would sit in the window for ten polls after the device came back, and a recovered device would keep alerting about the outage your down automation already paged you for.
- Only Down resets it. A missed poll that has not yet crossed your "Declare Down after" count is still a degraded device, not an outage โ it counts, filled with its timeout. The line between the two is your own missed-poll setting, not a second threshold hidden in here.
-
A recovered device is quiet until a group refills. Ten polls, so about
ten minutes at a 60-second cadence. That is a settling period rather than a blind
spot โ
downwas your down automation's business for the whole outage.
You can still change the number, or switch back to minutes, on any individual automation. The default only applies to a new automation that hasn't stated a window yet, and it never overrides a choice you have made.
Tick "Use multiple severity levels". A base severity moves into the condition group header, a + Severity button appears, and each added tier is its own accent-coloured block.
| Property | Behaviour |
|---|---|
| Severities | must strictly increase; thresholds need not be monotonic โ the most-severe met tier wins |
| Shared | metric, aggregation, window, dimension filter โ greyed on a tier |
| Editable per tier | operator and value, plus its own "Sustained for" |
| Max | 4 tiers |
| Actions | tiers can share the base actions, or have their own โ see Actions |
One alert climbs and eases in place rather than firing several. De-escalation is immediate, and the hysteresis dead band eases to the base severity.
A new tier defaults one rank above the previous and inherits the base's current hold, so adding one changes nothing until you edit it.
A metric with dimensions gets pickers, not free-text boxes, populated from what the draft's own scoped devices currently report, with per-value device counts.
For substring-matched dimensions (a sensor name, an interface, a mount) a match cue sits beside the field: "โ matches 2 of 14 reported hardware sensors", "โ exact match", or a warning that it "matches none โฆ would never fire". The dimension is a free-text pattern the server cannot reject, so without the cue a typo would save cleanly and then silently never match.
A stored value the devices no longer report is kept and flagged, never silently widened to "any".
The + Condition menu also offers:
- Device identifier โ Hostname / IP address / MAC address / Manufacturer / Model. Valid on every asset metric or state leaf.
- Component name โ Interface name / IPsec tunnel name / Storage mount / SD-WAN rule name.
Every per-component condition carries its component picker on the row itself and needs no filter row for it: the four interface conditions (Interface oper status, Interface admin status, Interface IP address, Interface PoE status) name an interface, and IPsec tunnel status names a tunnel. Click the box for the component names the scoped devices actually monitor. Leave it blank and the condition covers every monitored component, one alert each. A filter row still works there too โ it folds into the condition and re-opens on the row โ but the row is where these say what they are about.
One condition reaches further than the pins: a PoE fault. Interface PoE
status is fault (or other-fault) alerts on every PoE-capable port on the
scoped switches, whether or not you pinned it, and its picker lists those ports
rather than the pinned set. The reason is in the values themselves โ a port with
nothing plugged in reports searching, a port you switched PoE off on reports
disabled, so fault can only mean the switch found a powered device and
failed to power it. That is the one PoE failure nothing else tells you about:
the access point or camera on the far end never comes up, so it never becomes a
device that can go down. Three things follow:
-
It applies to
is faultonly. Written as is notdeliveringthe same condition would sweep in every empty and switched-off port in the fleet, so that form stays pinned-only. - Un-pinning does not switch it off. For every other interface condition, un-pinning the port is how you stop the alerts. For a PoE fault, narrow the automation's devices, or name a port pattern on the condition row.
- It counts in slow polls. On an unpinned port the reading comes from the full inventory scrape (every 10 minutes by default) rather than the fast monitoring pass, so a Sustained for of 3 polls is about half an hour. A faulted port does not flicker, so this delays the alert rather than missing it.
Be deliberate with the devices you scope it to: one failed PoE supply can fault every port on a switch at once, and Polaris raises one alert per port, each with its own email and its own Acknowledge button.
These render as "<what> matches <value>" rows and mean "narrow every
condition in this group". The stored rule never carries a filter row โ each
one is folded into its AND-group's leaves at save, and re-derived when you open
the automation again.
Matching semantics, mirrored client-side for the cue:
| Field | Matched as |
|---|---|
| Hostname, manufacturer, model | substring |
| IP address | CIDR / octet-boundary prefix / exact โ never bare substring |
| MAC address | separator-insensitive |
Device identifiers ride the trigger signature, so same-metric automations with different device filters never carve each other out.
The builder's pickers list the pin set, not the inventory (rule 57). An empty list reads as the gate, not as "this device has no ports". A filter that could never fire cannot be authored.
Every stream writes samples for unpinned members too, permanently inside the engine's lookback โ so the pin is a gate, never a side effect of retention.
SD-WAN member state and SD-WAN latency / jitter / packet loss conditions
can be narrowed by each member's current address
(rule 98). Add it with + Condition โ SD-WAN member
IP address. It is a filter row, like a health-check or hostname filter, and it
narrows every SD-WAN member condition in its group. Choose is not or is
and an address. The common use is SD-WAN member IP address is not 0.0.0.0,
which leaves out WAN ports with no address, such as a wan2 a template enabled
on every gate but nobody plugged in.
- A member is matched to the interface of the same name (
wan1,Overlay-1), and its current address is compared.0.0.0.0matches every form a gate reports for "no address". - A member whose address Polaris could not read (no interface row, or a scrape that returned no address) is always kept.
- A member that stops passing never raises an alert, and an alert already open on it clears.
-
Watch out: a DHCP WAN that loses its lease also reads
0.0.0.0while it is down, so is not 0.0.0.0 leaves that outage out too. Use an Interface oper status or SD-WAN member state automation without the filter if you need to hear about it.
Use the filter row rather than a separate Interface IP address is not 0.0.0.0 condition. With two conditions, each is checked across the whole device rather than on the same port: some other interface always has an address, so that second condition never filters anything.
The SD-WAN conditions are SD-WAN latency, SD-WAN jitter and SD-WAN packet loss (asset metrics) and SD-WAN member state (asset state). Each one is about a health check's view of a member. The condition row has a picker for each: health check and member.
Both pickers take more than one value. Click a name in the list to add it, and
click it again to remove it. Picked names show a โ, and the list stays open so
you can pick the next one. The box shows your picks separated by |, for
example Microsoft | Primary WAN. The sentence reads "for health check
Microsoft or Primary WAN".
- Any of them matches. A condition with several picks alerts on a member that matches any one of them.
-
Each pick matches part of a name, as a single value always has:
wanmatcheswan1andwan2. - Blank means all. Leave a picker empty to cover every health check or every member.
-
Typing filters the list by what you type after the last
|. - A pick that matches nothing is named by the match cue. The condition still fires on the other picks.
The member list follows the health checks you picked: it shows only the members of those health checks.
An SD-WAN alert email shows the member's last hour of latency, jitter and packet loss instead of the FortiGate's CPU, memory and response time. The FortiGate's own SLA targets are drawn as dashed lines. Stretches where the health check called the member down are shaded red.
The FortiGate stops reporting latency, jitter and loss for a member it has marked dead. If the member was down for the whole hour, each graph shows the red shading with no readings โ the health check reported this member down, rather than a line.
An overlay tunnel rides an underlay port: Overlay-3 over wan2. When wan2 loses packets, every overlay on it loses packets too. Polaris raises the wan2 alert and holds back the overlay alerts (rule 90).
- It applies to all four SD-WAN conditions above.
- An overlay is held back while its underlay is over the same line in the same automation, or while any automation has an open alert on the same condition about the underlay.
- An overlay is also held back while its underlay is down: the underlay's port is down, or it is dead on any health check. This applies even if the automation is narrowed to other health checks, or the underlay is in no health check at all.
- An overlay alert that was already open clears as superseded. No "resolved" notification is sent: the overlay has not recovered.
- An overlay whose underlay is healthy alerts as usual, and so does every other member on the same FortiGate.
Polaris learns which port a tunnel rides from the FortiGate's IPsec
configuration. A tunnel on a VLAN sub-interface (such as wan1.100) is traced
back to its physical port.
The Health Check Status strip on the device's SD-WAN tab also uses these automations: a poll that would cross one of their severity levels is coloured by that severity. See Assets.
"Test against current data" on the step, and on step 7 (the review) a full Devices this automation affects preview:
- Headlined by distinct devices, with readings spelled out separately โ a per-dimension metric evaluates one reading per sensor / interface / mount, so rows repeat the hostname. Each row names its dimension.
- A specificity indicator and the bidirectional carve-out warning.
- Carved-out devices are counted, not listed โ the rows are what the automation will alert on.
A default-checked "Reset when the trigger is no longer true", whose sentence says what that means rather than restating it: the trigger's own clause rendered inverted โ "CPU usage (avg over 5 minutes) is at or below 90 %", at the hysteresis clear threshold when one is set.
A 0/1 metric flips the value rather than the comparator โ "Hardware sensor alarm is OK", not "is not Alarm". A state to look for, not a double negative.
Two caveats are spelled out because you cannot read them off the clause:
- A monitor-status alert clears at the first successful probe, when the
status reads
recoveringโ which is the difference between "answered once" and "healthy again". - A numeric alert with no clear threshold resets at the very value that raised it, so a reading on the line can re-alert. The dead-band control is on the same step.
Unticking the box reveals Custom conditions first, then timed, then manual.
Custom conditions is the same AND/OR builder, seeded with the trigger inverted (De Morgan applied for a tree), so unticking lands on the editable spelling of what the box did โ not on "manually only". Offered on every trigger with a continuous condition (rule 32).
Four things it does:
- While firing, the tree is the sole recovery authority.
- Resolution is dimension-first: a reset condition on the same kind of component clears that component's alert alone โ one healthy port never clears another port's alert โ while a condition on something device-wide (CPU, memory, monitor status) clears them together. A reset condition also watches the same components the trigger does, including the unpinned PoE ports a fault condition covers (rule 57).
- Reset leaves carry no window control and inherit the trigger's measurement window โ a second minutes field beside "must stay true for" is exactly the window-vs-hold confusion the formula display exists to remove.
- A stored condition is kept verbatim and never re-seeded.
event and change triggers have nothing to invert, so they get "When a
matching event arrives" instead, prefilled from the server's known
counterparts โ agent.disconnected โ agent.connected, scoped to the same
subject the alert is about.
A new draft with a known counterpart lands on that mode rather than on a timer.
The known counterparts are agent.disconnected โ agent.connected,
agent.upgrade_failed / agent.upgrade_skipped โ agent.upgrade_succeeded,
agent.install_failed โ agent.installed, agent.uninstall_failed โ
agent.uninstalled, agent.build.failed โ agent.build.completed,
integration.discover.error โ integration.discover.completed,
platform.lifecycle_changed โ platform.lifecycle_recovered, and
capacity.severity_changed โ capacity.severity_recovered.
The all-clear is its own action, and it means fully recovered. Polaris
writes capacity.severity_recovered only when capacity lands back on OK โ
a drop from critical to warning keeps the ordinary
capacity.severity_changed, so the alert stays up while the host is still
degraded. Platform lifecycle works the same way. Two actions rather than one
because a reset matches on the action pattern alone: a rule pointed back at its
own trigger action would clear itself the moment it fired.
To be told about the all-clear, not just have it clear the alert, add an
action to the Reset Action list on the Actions step. The alert clearing is
silent by default โ the built-in rules ship with in-app alerts only and no
delivery channel, so they resolve the alert on the Alerts tab and write a
notification.auto_cleared Event (which reaches syslog/SFTP archival if you
have it configured) without emailing anyone.