Guides

Alerts in the SDK

Run kyr/1 rules on the engine’s files and streams, or headless in your own code.

Rules on the engine

The engine doesn’t store rules: hand it your whole list whenever it changes. Invalid rules are refused with their problems; the rest run on every file and stream open in the engine.

TypeScript
const problems = engine.alerts.setRules(rulesFromYourStore)
// [{ ruleId, code: 'unsupported_version', path: 'kyr' }, …]

engine.on('alert', (t) => {
  // t.kind: 'raised' | 'cleared' | 'lost'; t.t: the onset (raised) or the first false sample (cleared)
  console.log(t.kind, t.ruleId, t.target.name, t.t, t.peak)
})

engine.alerts.state()
// [{ ruleId, target: { kind: 'stream', id, name }, state: 'waiting', missing: ['Oil_Temp'] }, …]

Test on a loaded file

TypeScript
const id = await engine.datasets.addText(csv, 'run_042.csv')
const transitions = await engine.alerts.evaluate(id, { timeColumn: 'Time' })
engine.marks.list()   // [{ ruleId, ruleName, severity, targetId: id, timeColumn: 'Time', t0, t1 }]

Marks on the charts

Every raised alert becomes a mark: a span drawn on the charts whose X column is the time the rule ran on (ElapsedTime for live streams, the timeColumn you passed for files). Marks are read-only, never stored in chart settings, and painted in PNG exports. engine.alerts.clearMarks(id?) removes them. A chart view emits markselect with the rule id when the top edge of a mark is pressed.

Headless evaluator

@kymoscope/sdk/rules is the same evaluator as plain TypeScript, with no React and no DOM: use it in Node, a worker or a test.

TypeScript
import { createRuleEvaluator, validateRule } from '@kymoscope/sdk/rules'

const problems = validateRule(rule)               // [] when it can run
const ev = createRuleEvaluator(rule, { kind: 'stream', id: 'press-2', name: 'Press 2' })
ev.bind(['Oil_Temp', 'RPM'])                      // the channels this source has
const out = ev.push({
  t: Float64Array.from([0, 1, 2]),
  columns: { Oil_Temp: Float64Array.from([100, 121, 125]) },   // NaN: no sample at that row
})
ev.tick(10)                                       // advance time without samples (no-data rules)
ev.state()                                        // { state: 'active', since: 1, late: 0, lastT: 2 }

Limits

createEngine({ limits: { maxAlertRules: 10 } }) runs the first 10 valid rules and emits limit with reason alert-rules when there are more. See Limits and errors.