Skip to content

Incident

Template incident@1, analyst role: explains one incident on one asset, from the minutes before it (30 by default), over the asset and its related assets. It is triggered two ways:

  • An alarm going active, through an Event Stream. Ignition 8.3's Event Streams have no alarm source, so the trigger is an Event Stream you own, with an Event Listener source, fed by the alarms' Active Pipeline through one Script block, filtered to High and Critical, whose Script handler calls system.artekis.trigger. The Status page's step 8 holds the exact text to paste; in outline:
Event Stream Artekis/IncidentTrigger, source Event Listener
  Filter:  return int(event.data['priority']) >= 3
  Script handler:
    for e in events:
        system.artekis.trigger({'kind': 'alarm', 'at': e.data['at'], 'data': {'alarmPath': e.data['alarmPath']}})
Alarm pipeline (set as the alarms' Active Pipeline), one Script block:
    system.eventstream.publishEvent('<project>', 'Artekis/IncidentTrigger', system.util.jsonEncode({
        'alarmPath': str(event.source), 'priority': event.priority.ordinal,
        'at': system.date.format(system.date.fromMillis(event.activeData.timestamp),
                                 "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")}), False)
  • A line going down, from your own script: system.artekis.runPlaybook('<playbook>', {'kind': 'downtime', 'collection': 'line2', 'asset': 'line2.lact'}).

An incident needs an asset: data.alarmPath resolves to every enabled context model whose assets list the alarm or its tag (an alarm in two collections runs in both); an alarm no model lists is dropped and counted on Status. system.artekis.contextModel.assetFor(alarmPath) answers the same lookup from a script or view.

Look-back window. The run reads from the window's start up to the moment it begins. The window is the trigger's own window when the event carries one ({'value': 2, 'unit': 'HOURS'}), else the playbook's params.windowMinutes (a whole number of minutes, 1 to 1440, set in the playbook form as "Incident look-back (minutes)"), else 30 minutes — at most 24 hours either way. Lengthen it for processes that drift for a while before anything alarms. A playbook whose windowMinutes is not a whole number from 1 to 1440 is refused when it loads or is saved, and the refusal names the field.

The run offers six hypothesis families — the first-out alarm of the activation chain, the first tag excursion outside its normal range, an operator write, a configuration change, a communications loss, and "unexplained" — each with its evidence (timeline of activations, clears, acknowledgements, audit writes and config edits; trends of up to 20 tags; the asset's SOP passages from its linked documents, cited by file name and page — a doc <id> or char_offset the model writes is rewritten to the file and page when the finding is stored; how often each cause was seen before on this asset). The model ranks them, and the headline (highest confidence) lands on the asset's tags [Artekis]Collections/<c>/Assets/<asset>/Incident/LikelyCause, Confidence, ActionNow, FindingId, UpdatedAt, Json, LastFailedAt — LikelyCause reads "Analysing…" as soon as the trigger is accepted, the headline about a minute later (55 s measured), "No likely cause found" when nothing is above the floor. When a run fails, the asset's last good headline is put back and LastFailedAt records the failure time (an asset with none yet reads "Analysis failed — see Findings"); the next good headline clears LastFailedAt. Each "Trend of" evidence item carries the tag's context-model limits and normal range in its scope, as Anomaly Watch's do. After a module restart each asset's newest open headline is rebuilt from the store; an asset whose latest findings are all below the floor stays empty. Trends read the last stored value per interval, so a tag with no sample in an interval shows a gap, not 0.

A write says from what to what (1.5.15). An audit record holds only the value written, so each operator write in the window also carries the value the tag held just before it, read from its history (the last stored value in the 24 hours before the write), and the change: the writes table ev:inc:writes is [time, actor, action, target, value written, value before, change], the change reading "from 165 to 150 (down 15)". The operator-action hypothesis gets an item ev:inc:write:N (kind metric) with the before and after values, the direction and the difference, and, where the context model pairs the written setpoint with a reading (as the setpoint check does, FastShotVelSp ↔ FastShotVelIps), that reading's median over the 6 hours before the write and after it (to the run's end) and whether it moved the same way. The writer is told that the value held before a change is the one the process ran on, so a write that moves a setting away from it is a change made then, never a return to normal. With no history for the tag the table's last two columns are empty and no item is made. These history reads are at most 40 a run, none started more than 20 seconds after the run's reads began; past either, a write keeps only its written value.

Incident runs are urgent: queued first, never held by another run on the collection, allowed one slot above maxConcurrentAnalyses; two incidents on one asset run one after the other. Every stored finding is announced (repeatWindowHours does not apply); email is off in the shipped example. An Incident playbook takes event and script triggers only — a cron trigger is refused. The views pack ships Artekis/IncidentCard (params collection and assetId, or alarmPath), which binds those tags and needs the read level, and a disabled example playbook Artekis/Incident: replace its collection with yours and enable it. The card's title is the asset's name from the context model, and a failed latest analysis shows "Latest analysis failed at