Skip to content

Alarm Health

Reads the collection's alarm journal over the trigger's window (one day at a time, at most 500,000 transitions per run), runs the analyzers on the gateway and offers the model one candidate per symptom and alarm. The analyzers follow ISA-18.2 and EEMUA 191:

Family Candidate when Proposed change
nuisance chattering (3 or more activations within params.chatterWindowSeconds, default 60) or fleeting (at least half of 5+ cleared occurrences under 5 s) or too frequent to act on (more than 24 activations a day averaged over a window of a day or longer, or 10 or more within one hour; from 1.5.4) fleeting: timeOffDelaySeconds 5 (a clear delay: the alarm still comes in at once and stays active 5 s after the condition clears, so a blip is one event; the writer is told what the change does, and a writer sentence that names an on-delay with the proposed number, "an on-delay of about 5 s", is reworded to "a clear delay of about 5 s" when the finding is stored; no other sentence about delays is changed); chattering: timeOffDelaySeconds 15, plus a deadband of 2 % for a setpoint alarm whose deadband is smaller; too-frequent only: no change proposed (process class: the alarm tracks the process, for example a high level reached on every pump cycle, so its setpoint or purpose needs a person)
stale still active at window end, longer than params.staleHours (default 24). With the live alarm status read: only alarms it shows active, aged from the first activation after their last recorded clear: a re-activation with no clear recorded in between (a gateway restart or configuration change) does not reset the age. A standing alarm with no clear in the window that is past the limit, or whose window shows an older occurrence, has its journal read back up to 60 days before the window (at most 50 alarms, 500,000 transitions and 30 s, or a quarter of timeoutSeconds, a run); if that read fails, the age counts from the first activation inside the window, and if it stops early at a cap, from the oldest activation it read. With no clear found before it, the finding says "active since at least" and the KPI stale table's sinceAtLeast flag column is true. The finding names the re-activations, and does not resolve while the live status shows the alarm active and not cleared since. A shelved alarm counts as active: it is still filed past the limit, its finding says "(shelved)", and its row stays open. Without the live status: an occurrence with no clear and no later activation of the same alarm none
duplicate two alarms in one UDT instance (else one folder) activating within 2 s on 80 % of the rarer one's occurrences none
priority the Low / Medium / High activation share is 15 points or more off 80 / 15 / 5 none
flood any clock-aligned 10-minute period over params.floodThresholdPer10Min (default 10) none
rate more than 6 annunciated activations an hour on average none
restart-trip alarms in live alarm status (not the journal) that went active and cleared within 1 s of each other during the window: what a tag restart or configuration write leaves when a tag's initial value sits inside its own alarm range; listed with their mode, setpoint and active delay in the run's evidence (ev:ah:restart-trips), never filed as a finding since (a tag restart is the cause; a manager cannot act on it) none

Alarms at their own normal. A press's Down alarm that repeats 15 to 20 times a day, as it has for weeks, is not a finding. A nuisance candidate that is only too frequent, or only a minor chatterer (the bursts hold under 10 % of its activations), is left out when its rate in the window is at most 1.5 times its own average over the 28 days that end 14 days before the window starts, there is no burst of 10 or more in one hour, and the run is not truncated. The 28 days end at the earlier of two moments: 14 days before the window starts, and the day the alarm's open or hidden nuisance row was first filed. So a rate that only began with the row is never its own baseline, however long the row has stood, and a row filed at the alarm's long-standing rate closes on the next run (it is no longer seen). A row first filed more than 62 days before the window is not judged at all and keeps filing. It needs 14 days of journal before that end; if the journal does not reach back before the row was first filed (a fresh install), the end 14 days before the window is used until it does. If there is less than that, or the read fails or reaches the run deadline, every such alarm files as before. An alarm averaging more than 72 a day (3 times the 24 limit) always files. Fleeting alarms and chatterers with larger bursts are not affected. What was left out is listed in the evidence table ev:ah:at-own-normal (only alarms that file nothing).

A change made before a nuisance alarm started. Only nuisance candidates whose alarm activated at least 10 times in the window are looked at, the most active first. For each, the run reads the audit log (every profile, at most the newest 5,000 records per profile) from 7 days before the window start to the window end and keeps the tag writes and edits (not sign-ins) whose target lies in the alarm's asset's tag folder: the asset the context model lists the alarm or its tag under; its folder is the common folder of its tag paths: or on the alarm's own tag. Each is compared against the alarm's activations: after it, from the change for d whole days to the end of what the journal reads cover (1 to 7); before it, the same d days one week earlier, [change − 7 days, change − 7 days + d): the same days of the week, so a weekly rhythm (busy weekends) cancels even when the change is only a few days before the window end; with d = 7 it is simply the week before. A change less than a day before the window end, or whose week-earlier days fall before what the journal covers, is not judged. When a change sits less than 7 days into the window, the journal is also read for the 14 days before the window start (at most 500,000 transitions; past that, the window alone is used). A change is kept only when the alarm activated at least 3 times as often after it as in the same days a week earlier, and at least 10 times after it, and only when the alarm was not already up just before it: over the 7 − d days between the week-earlier days and the change (the last day before it when d = 7) its rate per day must be under a third of the after rate, so a flood that began before an operator's write is not reported as following it. A change followed by no such rise is left out however close it is. The item records the gap's days and its activations (gapDays, activationsJustBefore). With d below 7 the text reads "… in the same 5 days a week earlier and … in the 5 days after". Up to 3 kept changes, the strongest rise first, become one evidence item ev:ah:change:N (kind event, source audit-log; each change with its time, plant time, actor, action, target, written value, span in days, activations before and after, and per day), the same shape as Anomaly Watch's changes. The finding's text names the strongest in plant time: "Before it came in this often: operator set LS-5 lead on ft to 6.5 at Oct 19, 11:15 AM (audit log); it activated 3 times in the 7 days before that and 350 in the 7 days after (about 0.4 → 50 a day)." The audit record carries the written value only; since 1.5.15 the value the tag held just before the write is read from its history (its last stored value in the 24 hours before) and the text reads "set LS-5 lead on ft from 4.5 to 6.5", at most 40 such reads a run, each stopping at the run deadline; a tag with no history keeps "to 6.5". It says what was done and when, never that the change caused the alarms; the analyzer's own action then starts with that change, and the writer is told to consider it first among the causes. A writer's nuisance finding whose text does not already name the changed tag (its context-model name, else its last path segment in words; a mention of a value such as the alarm's setpoint does not count) gets the same sentence and the item; a sentence that would push a text past its length limit is left out whole, never cut. Every read in this lookup (audit log, earlier journal, tag history) stops at the run deadline: the playbook's timeoutSeconds from the start of the gather, less 2 minutes for the writer: with a log line. Nothing is looked up for stale or duplicate candidates (a rate before and after says nothing about one long activation or a pair), nor when the window's journal read was truncated. An audit log that cannot be read, or a gateway with no audit profile, names no change and the run goes on.

When no audit record explains it, the tag history. Many plants keep no audit profile but historize their setpoints. For a nuisance candidate no kept audit record explains, the run looks at the history of the asset's own setpoint, state and untyped tags (not read from a SQL source and not the alarm's own tag; at most 40 tags a run, the most active alarms' assets first). Each asset's tags are first counted with one aggregated Count read; a tag is then read raw, in one-minute intervals, unless it has no history or its count is clearly over one sample a minute across the span plus 1,000 (never past the platform's 200,000-sample raw limit). A count of 0, no count, or a count read that fails is not trusted, so the tag is read raw anyway; every tag left out is named, with why, in one log line a run. A tag whose Good numeric samples change at least once and at most 3 times, and that does not only ever read 0 and 1, is a setting; each change is a step dated to the start of the one-minute interval it happened within, judged by the same weekly rule. A tag that changes more often (a lead pump alternating every cycle, a running signal), a status or fault bit (0 and 1 only, latched or not) and a non-numeric tag are skipped. A kept step is listed with source historian, its old and new value and no actor. On a setpoint tag it reads "… changed from 4.5 to 6.5 ft"; on any other tag, since the history does not say a person made it, it is worded neutrally: Millbrook's LS-5 lead-start tag is a state tag, so "LS-5 lead pump start level went from 4.5 to 6.5 ft at Oct 19, 11:15 AM (from the tag's history; no audit record)": using the tag's context-model name and unit where it has them. The item is labeled "Setpoint changes in 's tag history" only when every listed change is on a setpoint tag, else "Changes in 's tag history". The analyzer's action asks whether the change brought the process to the alarm's setpoint only when the tag is a setpoint, or its unit in the context model is the alarm tag's and the step moved it toward (or onto) the alarm's setpoint; otherwise it asks what changed on the asset at that time. An audit record on the same tag within 10 minutes of a step is one change with it: the record is kept (it names who) and takes the step's old value. In practice a candidate an audit record already explains reads no history, so this only meets an audit record whose own rise did not qualify. A tag whose history cannot be read is skipped.

The top 10 alarms by count and by active time are evidence only. A proposed change uses Ignition's own property names and targets where the alarm is defined. When an instance inherits the alarm from a UDT type, the change is proposed on the type, and the finding states its reach: how many instances still inherit that alarm (a lower bound when the provider scan hit its 20,000-tag cap), how many are in this collection, and how many show the problem, with up to five examples. Artekis keeps UDTs templated: for an instance that still matches its type, the change on the type is the only proposal, however many instances show the problem. The finding also carries an "Or override on this instance only" alternative only when the instance is already overridden, meaning the alarm's own member tag carries a local tag property or an alarm of its own (parameter values, a memory tag's written value, the descriptive tooltip and documentation, and other members do not count), and then only when few instances show the problem (at most 25 %). The reach line ends with the instance's state: "this instance is templated", or "this instance already overrides PV (opcItemPath)". When the setpoint comes from a UDT parameter, the type change binds the deadband to an expression of that parameter, abs({HiSP}) * 0.02 with mode Absolute, so every instance clears at 2 % of its own setpoint. A deadband that is already bound (to a parameter, an expression or a tag) is never replaced; the change then carries the clear delay only. A Percent deadband is a share of the tag's engineering span, so a tag whose Engineering Low and High are not both set gets an Absolute deadband proposed instead.

Every run also builds the KPI document before the model is called: the ISA-18.2 KPIs with their benchmarks (alarms per hour, per day and per 10 minutes; peak 10 minutes; time in flood; priority distribution; the top 10's share; chattering, fleeting, stale and duplicate counts), the rate trend, the flood periods, the top alarms, per-area counts (an area is the topmost area asset above the alarm's asset), and, when params.shiftStarts lists HH:mm times in the settings timezone, per-shift counts and the alarms standing at each shift change. The KPIs feed the AlarmKPIs view and the PDF report (section 10); week-over-week compares with the newest earlier run of the same playbook and collection with the same window length, so two runs with the same window are needed before a comparison appears.