Event Alerts

Build typed conditions, thresholds, grouping, transitions, and absence detection on canonical ingest events.

Last verified 2026-08-30

Event Alerts evaluate canonical records in the HTTP, WebSocket, and Syslog ingest paths. Rules are compiled into a Data Model-scoped runtime cache; Core does not fetch or parse every rule for every event.

Governed conditions

Conditions use Data Model field names and controlled operators. Arbitrary SQL, JavaScript, templates, and executable expressions are rejected. Groups support and and or, with nested depth limited to 4 and at most 32 conditions.

Common operators are equals, not_equals, gt, gte, lt, lte, contains, starts_with, ends_with, exists, and not_exists. Core validates field existence and type/operator compatibility when a rule is created or updated. GET /api/v1/alerts/metadata returns the authoritative operator and safety-limit lists.

Trigger modes

ModeMeaning
every_matchTrigger when the compiled condition matches.
thresholdTrigger after at least threshold matches inside window_seconds.
distinct_thresholdTrigger after enough unique values of distinct_field inside the window.
transitionTrigger only when transition_field moves from the configured old value to the configured new value.
absenceTrigger when no matching event arrives for absence_seconds.

Up to 3 fields may form a deterministic group key. Events with the same group values merge into the same active Incident; different values create independent lifecycles. With no group fields, all matches for the rule share one active Incident. Avoid high-cardinality or time-varying fields such as timestamps. Core bounds active group cardinality and routes excess cardinality to a deterministic overflow group instead of growing state without limit.

Selected safe context fields do not affect grouping. They add up to 16 explicitly selected, non-secret values to bounded Occurrences and notification payloads so responders can investigate without including the full event. A distinct window retains at most 10,000 values, and windows are capped at 30 days.

Example: grouped failed logins

{
  "project_id": "PROJECT_ID",
  "name": "Repeated failed login",
  "description": "Ten failures from one source IP in five minutes",
  "enabled": true,
  "severity": "critical",
  "trigger_type": "event",
  "schema_id": "SECURITY_EVENTS_MODEL_ID",
  "conditions": {
    "combinator": "and",
    "conditions": [
      { "field": "event_type", "operator": "equals", "value": "login" },
      { "field": "outcome", "operator": "equals", "value": "failed" }
    ]
  },
  "group_by": ["source_ip"],
  "selected_fields": ["user_id", "source_ip", "outcome"],
  "trigger_mode": "threshold",
  "threshold": 10,
  "window_seconds": 300,
  "cooldown_seconds": 900,
  "channel_ids": ["SOC_CHANNEL_ID"]
}

Dedupe, state, and restart behavior

Evaluation state is stored transactionally in Core's database by Alert and group key. Row locking coordinates Core instances and the state survives restart. An active Incident is merged: last_seen_at and occurrence_count advance. The first qualifying match queues notification immediately. cooldown_seconds controls only later summary notifications for the same active Incident and must be at least 300 seconds; omitted or legacy zero values use the 300-second default. Resolving an Incident queues a closing notification and closes that lifecycle; a later match opens a new Incident.

Pending work for the same Incident and channel is coalesced. The dispatcher also enforces database-coordinated limits of 10 deliveries per channel per minute and 60 per project per minute. Deferred work remains queued rather than being dropped.

If the state store cannot be updated, Core does not create a positive Incident. The failure is logged and counted while normal ingest continues.

Testing and troubleshooting

Use POST /api/v1/alerts/{id}/simulate with {"event": {...}}. A NOT MATCHED response includes the condition-level reason. If live events do not trigger, verify that the rule and target Data Model are enabled, field types match, and the event passed ingest validation. A disabled Alert is removed from the compiled cache.

Was this page helpful?Send feedback